/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Test/Emit2/Emit/NumericIntPtrTests.cs
11 864 строки
609 KB
Jan Jones
Avoid evaluating platform-dependent shifts at compile time (#83034)
14 май 2026, 13:35
Не верифицирован
14 май 2026, 13:35
b2bb2fd
Код
Авторство
О чём код?
// 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. #nullable disable using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE; using Microsoft.CodeAnalysis.CSharp.Symbols.Retargeting; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.CSharp.UnitTests; using Microsoft.CodeAnalysis.Emit; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Roslyn.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics { public class NumericIntPtrTests : CSharpTestBase { private static string IncludeExpectedOutput(string expectedOutput) => ExecutionConditionUtil.IsMonoOrCoreClr ? expectedOutput : null; internal static readonly ConversionKind[] Identity = new[] { ConversionKind.Identity }; internal static readonly ConversionKind[] NoConversion = new[] { ConversionKind.NoConversion }; internal static readonly ConversionKind[] Boxing = new[] { ConversionKind.Boxing }; internal static readonly ConversionKind[] Unboxing = new[] { ConversionKind.Unboxing }; internal static readonly ConversionKind[] IntPtrConversion = new[] { ConversionKind.IntPtr }; internal static readonly ConversionKind[] ImplicitNumeric = new[] { ConversionKind.ImplicitNumeric }; internal static readonly ConversionKind[] ExplicitIntegerToPointer = new[] { ConversionKind.ExplicitIntegerToPointer }; internal static readonly ConversionKind[] ExplicitPointerToInteger = new[] { ConversionKind.ExplicitPointerToInteger }; internal static readonly ConversionKind[] ExplicitEnumeration = new[] { ConversionKind.ExplicitEnumeration }; internal static readonly ConversionKind[] ExplicitNumeric = new[] { ConversionKind.ExplicitNumeric }; internal static readonly ConversionKind[] ExplicitUserDefined = new[] { ConversionKind.ExplicitUserDefined }; internal static readonly ConversionKind[] ImplicitNullableNumeric = new[] { ConversionKind.ImplicitNullable, ConversionKind.ImplicitNumeric }; internal static readonly ConversionKind[] ImplicitNullableIdentity = new[] { ConversionKind.ImplicitNullable, ConversionKind.Identity }; internal static readonly ConversionKind[] ExplicitNullableEnumeration = new[] { ConversionKind.ExplicitNullable, ConversionKind.ExplicitEnumeration }; internal static readonly ConversionKind[] ExplicitNullableImplicitNumeric = new[] { ConversionKind.ExplicitNullable, ConversionKind.ImplicitNumeric }; internal static readonly ConversionKind[] ExplicitNullableNumeric = new[] { ConversionKind.ExplicitNullable, ConversionKind.ExplicitNumeric }; internal static readonly ConversionKind[] ExplicitNullablePointerToInteger = new[] { ConversionKind.ExplicitNullable, ConversionKind.ExplicitPointerToInteger }; internal static readonly ConversionKind[] ExplicitNullableIdentity = new[] { ConversionKind.ExplicitNullable, ConversionKind.Identity }; internal static readonly SymbolDisplayFormat TestFormat = SymbolDisplayFormat.TestFormat .RemoveCompilerInternalOptions(SymbolDisplayCompilerInternalOptions.UseNativeIntegerUnderlyingType); internal static readonly SymbolDisplayFormat ILFormat = SymbolDisplayFormat.ILVisualizationFormat .RemoveCompilerInternalOptions(SymbolDisplayCompilerInternalOptions.UseNativeIntegerUnderlyingType); internal static bool IsNoConversion(ConversionKind[] conversionKinds) { return conversionKinds is [ConversionKind.NoConversion]; } internal static void AssertMatches(ConversionKind[] expected, Conversion conversion) { IEnumerable<ConversionKind> actualConversionKinds = new[] { conversion.Kind }; if (!conversion.UnderlyingConversions.IsDefault) { actualConversionKinds = actualConversionKinds.Concat(conversion.UnderlyingConversions.Select(c => c.Kind)); } Assert.Equal(expected, actualConversionKinds); } private static int SymbolComparison(Symbol x, Symbol y) => SymbolComparison(x.ToTestDisplayString(), y.ToTestDisplayString()); private static int SymbolComparison(string x, string y) { return string.CompareOrdinal(normalizeDisplayString(x), normalizeDisplayString(y)); static string normalizeDisplayString(string s) => s.Replace("System.IntPtr", "nint").Replace("System.UIntPtr", "nuint"); } [Theory] [InlineData("System.IntPtr")] [InlineData("nint")] public void Interfaces(string type) { var sourceA = @"namespace System { public class Object { } public class String { } public abstract class ValueType { } public struct Void { } public struct Boolean { } public struct Int32 { } public interface ISerializable { } public interface IEquatable<T> { bool Equals(T other); } public interface IOther<T> { } public struct IntPtr : ISerializable, IEquatable<IntPtr>, IOther<IntPtr> { bool IEquatable<IntPtr>.Equals(IntPtr other) => false; } } " + RuntimeFeature_NumericIntPtr; var sourceB = $$""" using System; class Program { static void F0(ISerializable i) { } static object F1(IEquatable<IntPtr> i) => default; static void F2(IEquatable<nint> i) { } static void F3<T>(IOther<T> i) { } static void Main() { {{type}} n = 42; F0(n); F1(n); F2(n); F3<nint>(n); F3<IntPtr>(n); } } """; var comp = CreateEmptyCompilation(new[] { sourceA, sourceB }, parseOptions: TestOptions.Regular9); comp.VerifyDiagnostics(); } [Theory] [InlineData("System.UIntPtr")] [InlineData("nuint")] public void Interfaces_UIntPtr(string type) { var sourceA = @"namespace System { public class Object { } public class String { } public abstract class ValueType { } public struct Void { } public struct Boolean { } public struct Int32 { } public interface ISerializable { } public interface IEquatable<T> { bool Equals(T other); } public interface IOther<T> { } public struct UIntPtr : ISerializable, IEquatable<UIntPtr>, IOther<UIntPtr> { bool IEquatable<UIntPtr>.Equals(UIntPtr other) => false; } } " + RuntimeFeature_NumericIntPtr; var sourceB = $$""" using System; class Program { static void F0(ISerializable i) { } static object F1(IEquatable<UIntPtr> i) => default; static void F2(IEquatable<nuint> i) { } static void F3<T>(IOther<T> i) { } static void Main() { {{type}} n = 42; F0(n); F1(n); F2(n); F3<nuint>(n); F3<UIntPtr>(n); } } """; var comp = CreateEmptyCompilation(new[] { sourceA, sourceB }, parseOptions: TestOptions.Regular9); comp.VerifyDiagnostics(); } [Theory] [InlineData(false)] [InlineData(true)] public void StaticMembers(bool useCompilationReference) { var sourceA = @"namespace System { public class Object { } public class String { } public abstract class ValueType { } public struct Void { } public struct Boolean { } public struct Int32 { } public struct IntPtr { public static readonly IntPtr Zero; public static int Size => 0; public static IntPtr MaxValue => default; public static IntPtr MinValue => default; public static IntPtr Add(IntPtr ptr, int offset) => default; public static IntPtr Subtract(IntPtr ptr, int offset) => default; public static IntPtr Parse(string s) => default; public static bool TryParse(string s, out IntPtr value) { value = default; return false; } } public struct UIntPtr { public static readonly UIntPtr Zero; public static int Size => 0; public static UIntPtr MaxValue => default; public static UIntPtr MinValue => default; public static UIntPtr Add(UIntPtr ptr, int offset) => default; public static UIntPtr Subtract(UIntPtr ptr, int offset) => default; public static UIntPtr Parse(string s) => default; public static bool TryParse(string s, out UIntPtr value) { value = default; return false; } } public class Attribute { } public class AttributeUsageAttribute : Attribute { public AttributeUsageAttribute(AttributeTargets validOn) { } public bool AllowMultiple { get; set; } public bool Inherited { get; set; } } public struct Enum { } public enum AttributeTargets { } } " + RuntimeFeature_NumericIntPtr; var comp = CreateEmptyCompilation(sourceA); comp.VerifyDiagnostics(); var refA = AsReference(comp, useCompilationReference); var sourceB = @"class Program { static nint F1() { _ = nint.Zero; _ = nint.Size; var x1 = nint.MaxValue; var x2 = nint.MinValue; _ = nint.Add(x1, 2); _ = nint.Subtract(x1, 3); var x3 = nint.Parse(null); _ = nint.TryParse(null, out var x4); return 0; } static nuint F2() { _ = nuint.Zero; _ = nuint.Size; var y1 = nuint.MaxValue; var y2 = nuint.MinValue; _ = nuint.Add(y1, 2); _ = nuint.Subtract(y1, 3); var y3 = nuint.Parse(null); _ = nuint.TryParse(null, out var y4); return 0; } }"; comp = CreateEmptyCompilation(sourceB, references: new[] { refA }, parseOptions: TestOptions.Regular9); comp.VerifyDiagnostics(); } [Theory] [InlineData(false)] [InlineData(true)] public void InstanceMembers(bool useCompilationReference) { var sourceA = @"namespace System { public class Object { } public class String { } public abstract class ValueType { } public struct Void { } public struct Boolean { } public struct Int32 { } public struct Int64 { } public struct UInt32 { } public struct UInt64 { } public interface IFormatProvider { } public struct IntPtr { public int ToInt32() => default; public long ToInt64() => default; public uint ToUInt32() => default; public ulong ToUInt64() => default; unsafe public void* ToPointer() => default; public int CompareTo(object other) => default; public int CompareTo(IntPtr other) => default; public bool Equals(IntPtr other) => default; public string ToString(string format) => default; public string ToString(IFormatProvider provider) => default; public string ToString(string format, IFormatProvider provider) => default; } public struct UIntPtr { public int ToInt32() => default; public long ToInt64() => default; public uint ToUInt32() => default; public ulong ToUInt64() => default; unsafe public void* ToPointer() => default; public int CompareTo(object other) => default; public int CompareTo(UIntPtr other) => default; public bool Equals(UIntPtr other) => default; public string ToString(string format) => default; public string ToString(IFormatProvider provider) => default; public string ToString(string format, IFormatProvider provider) => default; } public class Attribute { } public class AttributeUsageAttribute : Attribute { public AttributeUsageAttribute(AttributeTargets t) { } public bool AllowMultiple { get; set; } public bool Inherited { get; set; } } public struct Enum { } public enum AttributeTargets { } } " + RuntimeFeature_NumericIntPtr; var comp = CreateEmptyCompilation(sourceA, options: TestOptions.UnsafeReleaseDll); comp.VerifyDiagnostics(); var refA = AsReference(comp, useCompilationReference); var sourceB = @"using System; class Program { unsafe static void F1(nint i) { _ = i.ToInt32(); _ = i.ToInt64(); _ = i.ToUInt32(); _ = i.ToUInt64(); _ = i.ToPointer(); _ = i.CompareTo(null); _ = i.CompareTo(i); _ = i.Equals(i); _ = i.ToString((string)null); _ = i.ToString((IFormatProvider)null); _ = i.ToString((string)null, (IFormatProvider)null); } unsafe static void F2(nuint u) { _ = u.ToInt32(); _ = u.ToInt64(); _ = u.ToUInt32(); _ = u.ToUInt64(); _ = u.ToPointer(); _ = u.CompareTo(null); _ = u.CompareTo(u); _ = u.Equals(u); _ = u.ToString((string)null); _ = u.ToString((IFormatProvider)null); _ = u.ToString((string)null, (IFormatProvider)null); } }"; comp = CreateEmptyCompilation(sourceB, references: new[] { refA }, parseOptions: TestOptions.Regular9, options: TestOptions.UnsafeReleaseDll); comp.VerifyDiagnostics(); } [Theory] [InlineData(false)] [InlineData(true)] public void ConstructorsAndOperators(bool useCompilationReference) { var sourceA = @"namespace System { public class Object { } public class String { } public abstract class ValueType { } public struct Void { } public struct Boolean { } public struct Int32 { } public struct Int64 { } public struct UInt32 { } public struct UInt64 { } public unsafe struct IntPtr { public IntPtr(int i) { } public IntPtr(long l) { } public IntPtr(void* p) { } public static explicit operator IntPtr(int i) => default; public static explicit operator IntPtr(long l) => default; public static explicit operator IntPtr(void* p) => default; public static explicit operator int(IntPtr i) => default; public static explicit operator long(IntPtr i) => default; public static explicit operator void*(IntPtr i) => default; public static IntPtr operator+(IntPtr x, int y) => default; public static IntPtr operator-(IntPtr x, int y) => default; public static bool operator==(IntPtr x, IntPtr y) => default; public static bool operator!=(IntPtr x, IntPtr y) => default; } public unsafe struct UIntPtr { public UIntPtr(uint i) { } public UIntPtr(ulong l) { } public UIntPtr(void* p) { } public static explicit operator UIntPtr(uint i) => default; public static explicit operator UIntPtr(ulong l) => default; public static explicit operator UIntPtr(void* p) => default; public static explicit operator uint(UIntPtr i) => default; public static explicit operator ulong(UIntPtr i) => default; public static explicit operator void*(UIntPtr i) => default; public static UIntPtr operator+(UIntPtr x, int y) => default; public static UIntPtr operator-(UIntPtr x, int y) => default; public static bool operator==(UIntPtr x, UIntPtr y) => default; public static bool operator!=(UIntPtr x, UIntPtr y) => default; } public class Attribute { } public class AttributeUsageAttribute : Attribute { public AttributeUsageAttribute(AttributeTargets t) { } public bool AllowMultiple { get; set; } public bool Inherited { get; set; } } public struct Enum { } public enum AttributeTargets { } } " + RuntimeFeature_NumericIntPtr; var comp = CreateEmptyCompilation(sourceA, options: TestOptions.UnsafeReleaseDll); comp.VerifyDiagnostics( // (12,26): warning CS0660: 'nint' defines operator == or operator != but does not override Object.Equals(object o) // public unsafe struct IntPtr Diagnostic(ErrorCode.WRN_EqualityOpWithoutEquals, "IntPtr").WithArguments("nint").WithLocation(12, 26), // (12,26): warning CS0661: 'nint' defines operator == or operator != but does not override Object.GetHashCode() // public unsafe struct IntPtr Diagnostic(ErrorCode.WRN_EqualityOpWithoutGetHashCode, "IntPtr").WithArguments("nint").WithLocation(12, 26), // (28,26): warning CS0660: 'nuint' defines operator == or operator != but does not override Object.Equals(object o) // public unsafe struct UIntPtr Diagnostic(ErrorCode.WRN_EqualityOpWithoutEquals, "UIntPtr").WithArguments("nuint").WithLocation(28, 26), // (28,26): warning CS0661: 'nuint' defines operator == or operator != but does not override Object.GetHashCode() // public unsafe struct UIntPtr Diagnostic(ErrorCode.WRN_EqualityOpWithoutGetHashCode, "UIntPtr").WithArguments("nuint").WithLocation(28, 26)); var refA = AsReference(comp, useCompilationReference); var sourceB = @"class Program { unsafe static void F1(nint x, nint y) { void* p = default; _ = new nint(); _ = new nint(1); _ = new nint(2L); _ = new nint(p); _ = (nint)1; _ = (nint)2L; _ = (nint)p; _ = (int)x; _ = (long)x; _ = (void*)x; _ = x + 1; _ = x - 2; _ = x == y; _ = x != y; } unsafe static void F2(nuint x, nuint y) { void* p = default; _ = new nuint(); _ = new nuint(1); _ = new nuint(2UL); _ = new nuint(p); _ = (nuint)1; _ = (nuint)2UL; _ = (nuint)p; _ = (uint)x; _ = (ulong)x; _ = (void*)x; _ = x + 1; _ = x - 2; _ = x == y; _ = x != y; } }"; comp = CreateEmptyCompilation(sourceB, references: new[] { refA }, parseOptions: TestOptions.Regular9, options: TestOptions.UnsafeReleaseDll); comp.VerifyDiagnostics(); } /// <summary> /// Overrides from IntPtr and UIntPtr are implicitly included on nint and nuint. /// </summary> [Theory] [InlineData(false)] [InlineData(true)] public void OverriddenMembers(bool useCompilationReference) { var sourceA = @"namespace System { public class Object { public virtual string ToString() => null; public virtual int GetHashCode() => 0; public virtual bool Equals(object obj) => false; } public class String { } public abstract class ValueType { public override string ToString() => null; public override int GetHashCode() => 0; public override bool Equals(object obj) => false; } public struct Void { } public struct Boolean { } public struct Int32 { } public struct IntPtr { public override string ToString() => null; public override int GetHashCode() => 0; public override bool Equals(object obj) => false; } public struct UIntPtr { public override string ToString() => null; public override int GetHashCode() => 0; public override bool Equals(object obj) => false; } public class Attribute { } public class AttributeUsageAttribute : Attribute { public AttributeUsageAttribute(AttributeTargets t) { } public bool AllowMultiple { get; set; } public bool Inherited { get; set; } } public struct Enum { } public enum AttributeTargets { } } " + RuntimeFeature_NumericIntPtr; var comp = CreateEmptyCompilation(sourceA); comp.VerifyDiagnostics(); var refA = AsReference(comp, useCompilationReference); var sourceB = @"class Program { static void F1(nint x, nint y) { _ = x.ToString(); _ = x.GetHashCode(); _ = x.Equals(y); } static void F2(nuint x, nuint y) { _ = x.ToString(); _ = x.GetHashCode(); _ = x.Equals(y); } }"; comp = CreateEmptyCompilation(sourceB, references: new[] { refA }, parseOptions: TestOptions.Regular9); comp.VerifyDiagnostics(); verifyType((NamedTypeSymbol)comp.GetMember<MethodSymbol>("Program.F1").Parameters[0].Type, signed: true); verifyType((NamedTypeSymbol)comp.GetMember<MethodSymbol>("Program.F2").Parameters[0].Type, signed: false); static void verifyType(NamedTypeSymbol type, bool signed) { var members = type.GetMembers().Sort(SymbolComparison); var actualMembers = members.SelectAsArray(m => m.ToDisplayString(TestFormat)); var expectedMembers = new[] { $"System.Boolean {type}.Equals(System.Object obj)", $"System.Int32 {type}.GetHashCode()", $"System.String {type}.ToString()", $"{type}..ctor()", }; AssertEx.Equal(expectedMembers, actualMembers); } } [Theory] [InlineData(false)] [InlineData(true)] public void ExplicitImplementations_01(bool useCompilationReference) { var sourceA = @"namespace System { public class Object { } public class String { } public abstract class ValueType { } public struct Void { } public struct Boolean { } public struct Int32 { } public struct Int64 { } public struct UInt32 { } public struct UInt64 { } public interface I<T> { T P { get; } T F(); } public struct IntPtr : I<IntPtr> { IntPtr I<IntPtr>.P => this; IntPtr I<IntPtr>.F() => this; } public struct UIntPtr : I<UIntPtr> { UIntPtr I<UIntPtr>.P => this; UIntPtr I<UIntPtr>.F() => this; } public class Attribute { } public class AttributeUsageAttribute : Attribute { public AttributeUsageAttribute(AttributeTargets t) { } public bool AllowMultiple { get; set; } public bool Inherited { get; set; } } public struct Enum { } public enum AttributeTargets { } } " + RuntimeFeature_NumericIntPtr; var comp = CreateEmptyCompilation(sourceA); comp.VerifyDiagnostics(); var refA = AsReference(comp, useCompilationReference); var sourceB = @"using System; class Program { static T F1<T>(I<T> t) { return default; } static I<T> F2<T>(I<T> t) { return t; } static void M1(nint x) { var x1 = F1(x); var x2 = F2(x).P; _ = x.P; _ = x.F(); } static void M2(nuint y) { var y1 = F1(y); var y2 = F2(y).P; _ = y.P; _ = y.F(); } static void M3(System.IntPtr x) { var z1 = F1(x); var z2 = F2(x).P; _ = x.P; _ = x.F(); } static void M4(System.UIntPtr y) { var t1 = F1(y); var t2 = F2(y).P; _ = y.P; _ = y.F(); } }"; comp = CreateEmptyCompilation(sourceB, references: new[] { refA }, parseOptions: TestOptions.Regular9); comp.VerifyDiagnostics( // (16,15): error CS1061: 'nint' does not contain a definition for 'P' and no accessible extension method 'P' accepting a first argument of type 'nint' could be found (are you missing a using directive or an assembly reference?) // _ = x.P; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "P").WithArguments("nint", "P").WithLocation(16, 15), // (17,15): error CS1061: 'nint' does not contain a definition for 'F' and no accessible extension method 'F' accepting a first argument of type 'nint' could be found (are you missing a using directive or an assembly reference?) // _ = x.F(); Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "F").WithArguments("nint", "F").WithLocation(17, 15), // (23,15): error CS1061: 'nuint' does not contain a definition for 'P' and no accessible extension method 'P' accepting a first argument of type 'nuint' could be found (are you missing a using directive or an assembly reference?) // _ = y.P; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "P").WithArguments("nuint", "P").WithLocation(23, 15), // (24,15): error CS1061: 'nuint' does not contain a definition for 'F' and no accessible extension method 'F' accepting a first argument of type 'nuint' could be found (are you missing a using directive or an assembly reference?) // _ = y.F(); Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "F").WithArguments("nuint", "F").WithLocation(24, 15), // (30,15): error CS1061: 'nint' does not contain a definition for 'P' and no accessible extension method 'P' accepting a first argument of type 'nint' could be found (are you missing a using directive or an assembly reference?) // _ = x.P; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "P").WithArguments("nint", "P").WithLocation(30, 15), // (31,15): error CS1061: 'nint' does not contain a definition for 'F' and no accessible extension method 'F' accepting a first argument of type 'nint' could be found (are you missing a using directive or an assembly reference?) // _ = x.F(); Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "F").WithArguments("nint", "F").WithLocation(31, 15), // (37,15): error CS1061: 'nuint' does not contain a definition for 'P' and no accessible extension method 'P' accepting a first argument of type 'nuint' could be found (are you missing a using directive or an assembly reference?) // _ = y.P; Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "P").WithArguments("nuint", "P").WithLocation(37, 15), // (38,15): error CS1061: 'nuint' does not contain a definition for 'F' and no accessible extension method 'F' accepting a first argument of type 'nuint' could be found (are you missing a using directive or an assembly reference?) // _ = y.F(); Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "F").WithArguments("nuint", "F").WithLocation(38, 15)); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var actualLocals = tree.GetRoot().DescendantNodes().OfType<VariableDeclaratorSyntax>().Select(d => model.GetDeclaredSymbol(d).ToDisplayString(TestFormat)); var expectedLocals = new[] { "nint x1", "nint x2", "nuint y1", "nuint y2", "nint z1", "nint z2", "nuint t1", "nuint t2", }; AssertEx.Equal(expectedLocals, actualLocals); } [Fact] public void NonPublicMembers_InternalUse() { var source = @"namespace System { public class Object { } public class String { } public abstract class ValueType { } public struct Void { } public struct Boolean { } public struct Int32 { } public struct IntPtr { private static IntPtr F1() => default; internal IntPtr F2() => default; public static IntPtr F3() { nint i = 0; _ = nint.F1(); _ = i.F2(); return nint.F3(); } public static nint F4() { IntPtr i = 0; _ = IntPtr.F1(); _ = i.F2(); return IntPtr.F3(); } } public struct UIntPtr { private static UIntPtr F1() => default; internal UIntPtr F2() => default; public static UIntPtr F3() { nuint i = 0; _ = nuint.F1(); _ = i.F2(); return nuint.F3(); } public static nuint F4() { UIntPtr i = 0; _ = UIntPtr.F1(); _ = i.F2(); return UIntPtr.F3(); } } } " + RuntimeFeature_NumericIntPtr; var comp = CreateEmptyCompilation(source, parseOptions: TestOptions.Regular9); comp.VerifyDiagnostics(); } [Theory] [InlineData(false)] [InlineData(true)] public void NonPublicMembers(bool useCompilationReference) { var sourceA = @"namespace System { public class Object { } public class String { } public abstract class ValueType { } public struct Void { } public struct Boolean { } public struct Int32 { } public struct IntPtr { private static IntPtr F1() => default; internal IntPtr F2() => default; public static IntPtr F3() => default; } public struct UIntPtr { private static UIntPtr F1() => default; internal UIntPtr F2() => default; public static UIntPtr F3() => default; } public class Attribute { } public class AttributeUsageAttribute : Attribute { public AttributeUsageAttribute(AttributeTargets t) { } public bool AllowMultiple { get; set; } public bool Inherited { get; set; } } public struct Enum { } public enum AttributeTargets { } } " + RuntimeFeature_NumericIntPtr; var comp = CreateEmptyCompilation(sourceA); comp.VerifyDiagnostics(); var refA = AsReference(comp, useCompilationReference); var sourceB = @"using System; class Program { static void F1(nint x) { _ = nint.F1(); _ = x.F2(); _ = nint.F3(); } static void F2(nuint y) { _ = nuint.F1(); _ = y.F2(); _ = nuint.F3(); } static void F3(IntPtr x) { _ = IntPtr.F1(); _ = x.F2(); _ = IntPtr.F3(); } static void F4(UIntPtr y) { _ = UIntPtr.F1(); _ = y.F2(); _ = UIntPtr.F3(); } }"; comp = CreateEmptyCompilation(sourceB, references: new[] { refA }, parseOptions: TestOptions.Regular9); if (useCompilationReference) { comp.VerifyDiagnostics( // (6,18): error CS0122: 'nint.F1()' is inaccessible due to its protection level // _ = nint.F1(); Diagnostic(ErrorCode.ERR_BadAccess, "F1").WithArguments("nint.F1()").WithLocation(6, 18), // (7,15): error CS0122: 'nint.F2()' is inaccessible due to its protection level // _ = x.F2(); Diagnostic(ErrorCode.ERR_BadAccess, "F2").WithArguments("nint.F2()").WithLocation(7, 15), // (12,19): error CS0122: 'nuint.F1()' is inaccessible due to its protection level // _ = nuint.F1(); Diagnostic(ErrorCode.ERR_BadAccess, "F1").WithArguments("nuint.F1()").WithLocation(12, 19), // (13,15): error CS0122: 'nuint.F2()' is inaccessible due to its protection level // _ = y.F2(); Diagnostic(ErrorCode.ERR_BadAccess, "F2").WithArguments("nuint.F2()").WithLocation(13, 15), // (18,20): error CS0122: 'nint.F1()' is inaccessible due to its protection level // _ = IntPtr.F1(); Diagnostic(ErrorCode.ERR_BadAccess, "F1").WithArguments("nint.F1()").WithLocation(18, 20), // (19,15): error CS0122: 'nint.F2()' is inaccessible due to its protection level // _ = x.F2(); Diagnostic(ErrorCode.ERR_BadAccess, "F2").WithArguments("nint.F2()").WithLocation(19, 15), // (24,21): error CS0122: 'nuint.F1()' is inaccessible due to its protection level // _ = UIntPtr.F1(); Diagnostic(ErrorCode.ERR_BadAccess, "F1").WithArguments("nuint.F1()").WithLocation(24, 21), // (25,15): error CS0122: 'nuint.F2()' is inaccessible due to its protection level // _ = y.F2(); Diagnostic(ErrorCode.ERR_BadAccess, "F2").WithArguments("nuint.F2()").WithLocation(25, 15)); } else { comp.VerifyDiagnostics( // (6,18): error CS0117: 'nint' does not contain a definition for 'F1' // _ = nint.F1(); Diagnostic(ErrorCode.ERR_NoSuchMember, "F1").WithArguments("nint", "F1").WithLocation(6, 18), // (7,15): error CS1061: 'nint' does not contain a definition for 'F2' and no accessible extension method 'F2' accepting a first argument of type 'nint' could be found (are you missing a using directive or an assembly reference?) // _ = x.F2(); Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "F2").WithArguments("nint", "F2").WithLocation(7, 15), // (12,19): error CS0117: 'nuint' does not contain a definition for 'F1' // _ = nuint.F1(); Diagnostic(ErrorCode.ERR_NoSuchMember, "F1").WithArguments("nuint", "F1").WithLocation(12, 19), // (13,15): error CS1061: 'nuint' does not contain a definition for 'F2' and no accessible extension method 'F2' accepting a first argument of type 'nuint' could be found (are you missing a using directive or an assembly reference?) // _ = y.F2(); Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "F2").WithArguments("nuint", "F2").WithLocation(13, 15), // (18,20): error CS0117: 'nint' does not contain a definition for 'F1' // _ = IntPtr.F1(); Diagnostic(ErrorCode.ERR_NoSuchMember, "F1").WithArguments("nint", "F1").WithLocation(18, 20), // (19,15): error CS1061: 'nint' does not contain a definition for 'F2' and no accessible extension method 'F2' accepting a first argument of type 'nint' could be found (are you missing a using directive or an assembly reference?) // _ = x.F2(); Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "F2").WithArguments("nint", "F2").WithLocation(19, 15), // (24,21): error CS0117: 'nuint' does not contain a definition for 'F1' // _ = UIntPtr.F1(); Diagnostic(ErrorCode.ERR_NoSuchMember, "F1").WithArguments("nuint", "F1").WithLocation(24, 21), // (25,15): error CS1061: 'nuint' does not contain a definition for 'F2' and no accessible extension method 'F2' accepting a first argument of type 'nuint' could be found (are you missing a using directive or an assembly reference?) // _ = y.F2(); Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "F2").WithArguments("nuint", "F2").WithLocation(25, 15)); } } [Fact] public void Overrides_01() { var sourceA = @"public interface IA { void F1(nint x, System.UIntPtr y); } public abstract class A { public abstract void F2(System.IntPtr x, nuint y); }"; var sourceB = @"class B1 : A, IA { public void F1(nint x, System.UIntPtr y) { } public override void F2(System.IntPtr x, nuint y) { } } class B2 : A, IA { public void F1(System.IntPtr x, nuint y) { } public override void F2(nint x, System.UIntPtr y) { } } class A3 : IA { void IA.F1(nint x, System.UIntPtr y) { } } class A4 : IA { void IA.F1(System.IntPtr x, nuint y) { } }"; var comp = CreateCompilation(new[] { sourceA, sourceB }, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); comp = CreateCompilation(sourceA, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); var ref1 = comp.ToMetadataReference(); var ref2 = comp.EmitToImageReference(); comp = CreateCompilation(sourceB, references: new[] { ref1 }, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); comp = CreateCompilation(sourceB, references: new[] { ref2 }, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); } [Fact] public void Overloads_01() { var sourceA = @"public class A { public void F1(System.IntPtr x) { } public void F2(nuint y) { } }"; var sourceB = @"class B1 : A { public void F1(nuint x) { } public void F2(System.IntPtr y) { } } class B2 : A { public void F1(nint x) { base.F1(x); } public void F2(System.UIntPtr y) { base.F2(y); } } class B3 : A { public new void F1(nuint x) { } public new void F2(System.IntPtr y) { } } class B4 : A { public new void F1(nint x) { base.F1(x); } public new void F2(System.UIntPtr y) { base.F2(y); } }"; var diagnostics = new[] { // (8,17): warning CS0108: 'B2.F1(nint)' hides inherited member 'A.F1(nint)'. Use the new keyword if hiding was intended. // public void F1(nint x) { base.F1(x); } Diagnostic(ErrorCode.WRN_NewRequired, "F1").WithArguments("B2.F1(nint)", "A.F1(nint)").WithLocation(8, 17), // (9,17): warning CS0108: 'B2.F2(nuint)' hides inherited member 'A.F2(nuint)'. Use the new keyword if hiding was intended. // public void F2(System.UIntPtr y) { base.F2(y); } Diagnostic(ErrorCode.WRN_NewRequired, "F2").WithArguments("B2.F2(nuint)", "A.F2(nuint)").WithLocation(9, 17), // (13,21): warning CS0109: The member 'B3.F1(nuint)' does not hide an accessible member. The new keyword is not required. // public new void F1(nuint x) { } Diagnostic(ErrorCode.WRN_NewNotRequired, "F1").WithArguments("B3.F1(nuint)").WithLocation(13, 21), // (14,21): warning CS0109: The member 'B3.F2(nint)' does not hide an accessible member. The new keyword is not required. // public new void F2(System.IntPtr y) { } Diagnostic(ErrorCode.WRN_NewNotRequired, "F2").WithArguments("B3.F2(nint)").WithLocation(14, 21) }; var comp = CreateCompilation(new[] { sourceA, sourceB }, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(diagnostics); comp = CreateCompilation(sourceA, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); var ref1 = comp.ToMetadataReference(); var ref2 = comp.EmitToImageReference(); comp = CreateCompilation(sourceB, references: new[] { ref1 }, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(diagnostics); comp = CreateCompilation(sourceB, references: new[] { ref2 }, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(diagnostics); } [Fact] public void Partial_01() { var source = @"partial class Program { static partial void F1(System.IntPtr x); static partial void F2(System.UIntPtr x) { } static partial void F1(nint x) { } static partial void F2(nuint x); }"; var comp = CreateCompilation(source, options: TestOptions.ReleaseDll.WithWarningLevel(5), parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); comp = CreateCompilation(source, options: TestOptions.ReleaseDll.WithWarningLevel(6), parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); } [Fact, WorkItem(63860, "https://github.com/dotnet/roslyn/issues/63860")] public void AddUIntPtrAndInt() { var source = @" using System; class C { UIntPtr M(UIntPtr i, int j) => i + j; } "; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics( // (6,36): error CS0034: Operator '+' is ambiguous on operands of type 'nuint' and 'int' // UIntPtr M(UIntPtr i, int j) => i + j; Diagnostic(ErrorCode.ERR_AmbigBinaryOps, "i + j").WithArguments("+", "nuint", "int").WithLocation(6, 36) ); comp = CreateCompilation(source); comp.VerifyDiagnostics(); var verifier = CompileAndVerify(comp); verifier.VerifyIL("C.M", @" { // Code size 8 (0x8) .maxstack 2 IL_0000: ldarg.1 IL_0001: ldarg.2 IL_0002: call ""System.UIntPtr System.UIntPtr.op_Addition(System.UIntPtr, int)"" IL_0007: ret } "); } [Fact, WorkItem(63860, "https://github.com/dotnet/roslyn/issues/63860")] public void AddNUIntAndInt() { var source = @" class C { nuint M(nuint i, int j) => i + j; }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics( // (4,32): error CS0034: Operator '+' is ambiguous on operands of type 'nuint' and 'int' // nuint M(nuint i, int j) => i + j; Diagnostic(ErrorCode.ERR_AmbigBinaryOps, "i + j").WithArguments("+", "nuint", "int").WithLocation(4, 32) ); comp = CreateCompilation(source); comp.VerifyDiagnostics( // (4,32): error CS0034: Operator '+' is ambiguous on operands of type 'nuint' and 'int' // nuint M(nuint i, int j) => i + j; Diagnostic(ErrorCode.ERR_AmbigBinaryOps, "i + j").WithArguments("+", "nuint", "int").WithLocation(4, 32) ); } [Fact, WorkItem(63860, "https://github.com/dotnet/roslyn/issues/63860")] public void AddIntPtrAndInt() { var source = @" using System; class C { IntPtr M(IntPtr i, int j) => i + j; }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); var verifier = CompileAndVerify(comp, verify: Verification.FailsPEVerify); verifier.VerifyIL("C.M", @" { // Code size 5 (0x5) .maxstack 2 IL_0000: ldarg.1 IL_0001: ldarg.2 IL_0002: conv.i IL_0003: add IL_0004: ret } "); comp = CreateCompilation(source); comp.VerifyDiagnostics(); verifier = CompileAndVerify(comp); verifier.VerifyIL("C.M", @" { // Code size 8 (0x8) .maxstack 2 IL_0000: ldarg.1 IL_0001: ldarg.2 IL_0002: call ""System.IntPtr System.IntPtr.op_Addition(System.IntPtr, int)"" IL_0007: ret } "); } [Fact, WorkItem(63860, "https://github.com/dotnet/roslyn/issues/63860")] public void AddNIntAndInt() { var source = @" class C { nint M(nint i, int j) => i + j; }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); var verifier = CompileAndVerify(comp, verify: Verification.FailsPEVerify); verifier.VerifyIL("C.M", @" { // Code size 5 (0x5) .maxstack 2 IL_0000: ldarg.1 IL_0001: ldarg.2 IL_0002: conv.i IL_0003: add IL_0004: ret } "); comp = CreateCompilation(source); comp.VerifyDiagnostics(); verifier = CompileAndVerify(comp); verifier.VerifyIL("C.M", @" { // Code size 5 (0x5) .maxstack 2 IL_0000: ldarg.1 IL_0001: ldarg.2 IL_0002: conv.i IL_0003: add IL_0004: ret } "); } [Fact] public void Constraints_01() { var sourceA = @"public class A<T> { public static void F<U>() where U : T { } } public class B1 : A<nint> { } public class B2 : A<nuint> { } public class B3 : A<System.IntPtr> { } public class B4 : A<System.UIntPtr> { } "; var sourceB = @"class Program { static void Main() { B1.F<System.IntPtr>(); B2.F<System.UIntPtr>(); B3.F<nint>(); B4.F<nuint>(); } }"; var comp = CreateCompilation(new[] { sourceA, sourceB }, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); comp = CreateCompilation(sourceA, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); var ref1 = comp.ToMetadataReference(); var ref2 = comp.EmitToImageReference(); comp = CreateCompilation(sourceB, references: new[] { ref1 }, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); comp = CreateCompilation(sourceB, references: new[] { ref2 }, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); } [Fact] public void AttributeType_01() { var source = @"[nint] [A, nuint()] class Program { } class AAttribute : System.Attribute { }"; var expectedDiagnostics = new[] { // (1,2): error CS0246: The type or namespace name 'nintAttribute' could not be found (are you missing a using directive or an assembly reference?) // [nint] Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "nint").WithArguments("nintAttribute").WithLocation(1, 2), // (1,2): error CS0246: The type or namespace name 'nint' could not be found (are you missing a using directive or an assembly reference?) // [nint] Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "nint").WithArguments("nint").WithLocation(1, 2), // (2,5): error CS0246: The type or namespace name 'nuintAttribute' could not be found (are you missing a using directive or an assembly reference?) // [A, nuint] Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "nuint").WithArguments("nuintAttribute").WithLocation(2, 5), // (2,5): error CS0246: The type or namespace name 'nuint' could not be found (are you missing a using directive or an assembly reference?) // [A, nuint] Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "nuint").WithArguments("nuint").WithLocation(2, 5) }; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(expectedDiagnostics); comp = CreateCompilation(source, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(expectedDiagnostics); } [Fact] public void NameOf_01() { var source = @"using System; class Program { static void Main() { Console.WriteLine(nameof(nint)); Console.WriteLine(nameof(nuint)); } }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics( // (6,34): error CS0103: The name 'nint' does not exist in the current context // Console.WriteLine(nameof(nint)); Diagnostic(ErrorCode.ERR_NameNotInContext, "nint").WithArguments("nint").WithLocation(6, 34), // (7,34): error CS0103: The name 'nuint' does not exist in the current context // Console.WriteLine(nameof(nuint)); Diagnostic(ErrorCode.ERR_NameNotInContext, "nuint").WithArguments("nuint").WithLocation(7, 34)); } [Fact] public void NameOf_04() { var source = @"class Program { static void F(int @nint, uint @nuint) { _ = nameof(@nint); _ = nameof(@nuint); } }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); comp = CreateCompilation(source, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); } [Fact] public void SizeOf_01() { var source = @"class Program { static void Main() { _ = sizeof(System.IntPtr); _ = sizeof(System.UIntPtr); _ = sizeof(nint); _ = sizeof(nuint); } }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics( // (5,13): error CS0233: 'nint' does not have a predefined size, therefore sizeof can only be used in an unsafe context // _ = sizeof(System.IntPtr); Diagnostic(ErrorCode.ERR_SizeofUnsafe, "sizeof(System.IntPtr)").WithArguments("nint").WithLocation(5, 13), // (6,13): error CS0233: 'nuint' does not have a predefined size, therefore sizeof can only be used in an unsafe context // _ = sizeof(System.UIntPtr); Diagnostic(ErrorCode.ERR_SizeofUnsafe, "sizeof(System.UIntPtr)").WithArguments("nuint").WithLocation(6, 13), // (7,13): error CS0233: 'nint' does not have a predefined size, therefore sizeof can only be used in an unsafe context // _ = sizeof(nint); Diagnostic(ErrorCode.ERR_SizeofUnsafe, "sizeof(nint)").WithArguments("nint").WithLocation(7, 13), // (8,13): error CS0233: 'nuint' does not have a predefined size, therefore sizeof can only be used in an unsafe context // _ = sizeof(nuint); Diagnostic(ErrorCode.ERR_SizeofUnsafe, "sizeof(nuint)").WithArguments("nuint").WithLocation(8, 13)); } [Fact] public void SizeOf_02() { var source = @"using System; class Program { unsafe static void Main() { Console.Write(sizeof(System.IntPtr)); Console.Write(sizeof(System.UIntPtr)); Console.Write(sizeof(nint)); Console.Write(sizeof(nuint)); } }"; var comp = CreateCompilation(source, options: TestOptions.UnsafeReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); int size = IntPtr.Size; var verifier = CompileAndVerify(comp, expectedOutput: IncludeExpectedOutput($"{size}{size}{size}{size}"), verify: Verification.FailsPEVerify); verifier.VerifyIL("Program.Main", @"{ // Code size 45 (0x2d) .maxstack 1 IL_0000: sizeof ""nint"" IL_0006: call ""void System.Console.Write(int)"" IL_000b: sizeof ""nuint"" IL_0011: call ""void System.Console.Write(int)"" IL_0016: sizeof ""nint"" IL_001c: call ""void System.Console.Write(int)"" IL_0021: sizeof ""nuint"" IL_0027: call ""void System.Console.Write(int)"" IL_002c: ret }", ilFormat: ILFormat); } [Fact] public void SizeOf_03() { var source = @"using System.Collections.Generic; unsafe class Program { static IEnumerable<int> F() { yield return sizeof(nint); yield return sizeof(nuint); yield return sizeof(System.IntPtr); yield return sizeof(System.UIntPtr); } }"; // https://github.com/dotnet/roslyn/issues/73280 - should not be a langversion error since this remains an error in C# 13 CreateCompilation(source, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70).VerifyDiagnostics( // (6,22): error CS8773: Feature 'ref and unsafe in async and iterator methods' is not available in C# 9.0. Please use language version 13.0 or greater. // yield return sizeof(nint); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "sizeof(nint)").WithArguments("ref and unsafe in async and iterator methods", "13.0").WithLocation(6, 22), // (7,22): error CS8773: Feature 'ref and unsafe in async and iterator methods' is not available in C# 9.0. Please use language version 13.0 or greater. // yield return sizeof(nuint); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "sizeof(nuint)").WithArguments("ref and unsafe in async and iterator methods", "13.0").WithLocation(7, 22), // (8,22): error CS8773: Feature 'ref and unsafe in async and iterator methods' is not available in C# 9.0. Please use language version 13.0 or greater. // yield return sizeof(System.IntPtr); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "sizeof(System.IntPtr)").WithArguments("ref and unsafe in async and iterator methods", "13.0").WithLocation(8, 22), // (9,22): error CS8773: Feature 'ref and unsafe in async and iterator methods' is not available in C# 9.0. Please use language version 13.0 or greater. // yield return sizeof(System.UIntPtr); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "sizeof(System.UIntPtr)").WithArguments("ref and unsafe in async and iterator methods", "13.0").WithLocation(9, 22) ); CreateCompilation(source, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular12, targetFramework: TargetFramework.Net70).VerifyDiagnostics( // (6,22): error CS9202: Feature 'ref and unsafe in async and iterator methods' is not available in C# 12.0. Please use language version 13.0 or greater. // yield return sizeof(nint); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion12, "sizeof(nint)").WithArguments("ref and unsafe in async and iterator methods", "13.0").WithLocation(6, 22), // (7,22): error CS9202: Feature 'ref and unsafe in async and iterator methods' is not available in C# 12.0. Please use language version 13.0 or greater. // yield return sizeof(nuint); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion12, "sizeof(nuint)").WithArguments("ref and unsafe in async and iterator methods", "13.0").WithLocation(7, 22), // (8,22): error CS9202: Feature 'ref and unsafe in async and iterator methods' is not available in C# 12.0. Please use language version 13.0 or greater. // yield return sizeof(System.IntPtr); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion12, "sizeof(System.IntPtr)").WithArguments("ref and unsafe in async and iterator methods", "13.0").WithLocation(8, 22), // (9,22): error CS9202: Feature 'ref and unsafe in async and iterator methods' is not available in C# 12.0. Please use language version 13.0 or greater. // yield return sizeof(System.UIntPtr); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion12, "sizeof(System.UIntPtr)").WithArguments("ref and unsafe in async and iterator methods", "13.0").WithLocation(9, 22) ); var expectedDiagnostics = new[] { // (6,22): error CS0233: 'nint' does not have a predefined size, therefore sizeof can only be used in an unsafe context // yield return sizeof(nint); Diagnostic(ErrorCode.ERR_SizeofUnsafe, "sizeof(nint)").WithArguments("nint").WithLocation(6, 22), // (7,22): error CS0233: 'nuint' does not have a predefined size, therefore sizeof can only be used in an unsafe context // yield return sizeof(nuint); Diagnostic(ErrorCode.ERR_SizeofUnsafe, "sizeof(nuint)").WithArguments("nuint").WithLocation(7, 22), // (8,22): error CS0233: 'nint' does not have a predefined size, therefore sizeof can only be used in an unsafe context // yield return sizeof(System.IntPtr); Diagnostic(ErrorCode.ERR_SizeofUnsafe, "sizeof(System.IntPtr)").WithArguments("nint").WithLocation(8, 22), // (9,22): error CS0233: 'nuint' does not have a predefined size, therefore sizeof can only be used in an unsafe context // yield return sizeof(System.UIntPtr); Diagnostic(ErrorCode.ERR_SizeofUnsafe, "sizeof(System.UIntPtr)").WithArguments("nuint").WithLocation(9, 22) }; CreateCompilation(source, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular13, targetFramework: TargetFramework.Net70).VerifyDiagnostics(expectedDiagnostics); CreateCompilation(source, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular14, targetFramework: TargetFramework.Net70).VerifyDiagnostics(expectedDiagnostics); CreateCompilation(source, options: TestOptions.UnsafeReleaseDll, targetFramework: TargetFramework.Net70).VerifyDiagnostics(); CreateCompilation(source, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.RegularNext, targetFramework: TargetFramework.Net70).VerifyDiagnostics(); } [Fact] public void TypeOf() { var source = @"using static System.Console; class Program { static void Main() { var t1 = typeof(nint); var t2 = typeof(nuint); var t3 = typeof(System.IntPtr); var t4 = typeof(System.UIntPtr); WriteLine(t1.FullName); WriteLine(t2.FullName); WriteLine((object)t1 == t2); WriteLine((object)t1 == t3); WriteLine((object)t2 == t4); } }"; var comp = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); CompileAndVerify(comp, verify: Verification.FailsPEVerify, expectedOutput: IncludeExpectedOutput( @"System.IntPtr System.UIntPtr False True True")); } [Fact] public void Volatile() { var source = @"using System; class Program { static volatile IntPtr F1 = -1; static volatile UIntPtr F2 = 2; static IntPtr F() => F1 + (IntPtr)F2; static void Main() { System.Console.WriteLine(F()); } }"; var comp = CreateCompilation(source, options: TestOptions.ReleaseExe, targetFramework: TargetFramework.Net70); var verifier = CompileAndVerify(comp, expectedOutput: IncludeExpectedOutput(@"1"), verify: Verification.FailsPEVerify); verifier.VerifyIL("Program.F", @"{ // Code size 16 (0x10) .maxstack 2 IL_0000: volatile. IL_0002: ldsfld ""nint Program.F1"" IL_0007: volatile. IL_0009: ldsfld ""nuint Program.F2"" IL_000e: add IL_000f: ret }", ilFormat: ILFormat); } [Fact] public void MultipleTypeRefs_01() { string source = @"class Program { static string F1(nint i) { return i.ToString(); } static object F2(nint i) { return i; } static void Main() { System.Console.WriteLine(F1(-42)); System.Console.WriteLine(F2(42)); } }"; var comp = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); var verifier = CompileAndVerify(comp, verify: Verification.FailsPEVerify, expectedOutput: IncludeExpectedOutput( @"-42 42")); verifier.VerifyIL("Program.F1", @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""string nint.ToString()"" IL_0007: ret }", ilFormat: ILFormat); verifier.VerifyIL("Program.F2", @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: box ""nint"" IL_0006: ret }", ilFormat: ILFormat); } /// <summary> /// Verify there is the number of built in operators for { IntPtr, UIntPtr, IntPtr?, UIntPtr? } /// for each operator kind. /// </summary> [Fact] public void BuiltInOperators() { var comp = CreateCompilation("", parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); verifyOperators(comp); static void verifyOperators(CSharpCompilation comp) { var unaryOperators = new[] { UnaryOperatorKind.PostfixIncrement, UnaryOperatorKind.PostfixDecrement, UnaryOperatorKind.PrefixIncrement, UnaryOperatorKind.PrefixDecrement, UnaryOperatorKind.UnaryPlus, UnaryOperatorKind.UnaryMinus, UnaryOperatorKind.BitwiseComplement, }; var binaryOperators = new[] { BinaryOperatorKind.Addition, BinaryOperatorKind.Subtraction, BinaryOperatorKind.Multiplication, BinaryOperatorKind.Division, BinaryOperatorKind.Remainder, BinaryOperatorKind.LessThan, BinaryOperatorKind.LessThanOrEqual, BinaryOperatorKind.GreaterThan, BinaryOperatorKind.GreaterThanOrEqual, BinaryOperatorKind.LeftShift, BinaryOperatorKind.RightShift, BinaryOperatorKind.Equal, BinaryOperatorKind.NotEqual, BinaryOperatorKind.Or, BinaryOperatorKind.And, BinaryOperatorKind.Xor, BinaryOperatorKind.UnsignedRightShift, }; foreach (var operatorKind in unaryOperators) { verifyUnaryOperators(comp, operatorKind, skipNativeIntegerOperators: true); verifyUnaryOperators(comp, operatorKind, skipNativeIntegerOperators: false); } foreach (var operatorKind in binaryOperators) { verifyBinaryOperators(comp, operatorKind, skipNativeIntegerOperators: true); verifyBinaryOperators(comp, operatorKind, skipNativeIntegerOperators: false); } static void verifyUnaryOperators(CSharpCompilation comp, UnaryOperatorKind operatorKind, bool skipNativeIntegerOperators) { var builder = ArrayBuilder<UnaryOperatorSignature>.GetInstance(); comp.BuiltInOperators.GetSimpleBuiltInOperators(operatorKind, builder, skipNativeIntegerOperators); var operators = builder.ToImmutableAndFree(); int expectedSigned = skipNativeIntegerOperators ? 0 : 1; int expectedUnsigned = skipNativeIntegerOperators ? 0 : (operatorKind == UnaryOperatorKind.UnaryMinus) ? 0 : 1; verifyOperators(operators, (op, signed) => isNativeInt(op.OperandType, signed), expectedSigned, expectedUnsigned); verifyOperators(operators, (op, signed) => isNullableNativeInt(op.OperandType, signed), expectedSigned, expectedUnsigned); } static void verifyBinaryOperators(CSharpCompilation comp, BinaryOperatorKind operatorKind, bool skipNativeIntegerOperators) { var builder = ArrayBuilder<BinaryOperatorSignature>.GetInstance(); comp.BuiltInOperators.GetSimpleBuiltInOperators(operatorKind, builder, skipNativeIntegerOperators); var operators = builder.ToImmutableAndFree(); int expected = skipNativeIntegerOperators ? 0 : 1; verifyOperators(operators, (op, signed) => isNativeInt(op.LeftType, signed), expected, expected); verifyOperators(operators, (op, signed) => isNullableNativeInt(op.LeftType, signed), expected, expected); } static void verifyOperators<T>(ImmutableArray<T> operators, Func<T, bool, bool> predicate, int expectedSigned, int expectedUnsigned) { Assert.Equal(expectedSigned, operators.Count(op => predicate(op, true))); Assert.Equal(expectedUnsigned, operators.Count(op => predicate(op, false))); } static bool isNativeInt(TypeSymbol type, bool signed) { return type.SpecialType == (signed ? SpecialType.System_IntPtr : SpecialType.System_UIntPtr); } static bool isNullableNativeInt(TypeSymbol type, bool signed) { return type.IsNullableType() && isNativeInt(type.GetNullableUnderlyingType(), signed); } } } [Theory, CombinatorialData] public void BuiltInConversions_NativeIntegers(bool useCompilationReference, bool useLatest, bool useSystemTypes) { var nintType = useSystemTypes ? "System.IntPtr" : "nint"; var nuintType = useSystemTypes ? "System.UIntPtr" : "nuint"; var sourceA = $$""" public class A { public static {{nintType}} F1; public static {{nuintType}} F2; public static {{nintType}}? F3; public static {{nuintType}}? F4; } """; var comp = CreateCompilation(sourceA, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); var sourceB = @"class B : A { static void M1() { long x = F1; ulong y = F2; long? z = F3; ulong? w = F4; } static void M2(int x, uint y, int? z, uint? w) { F1 = x; F2 = y; F3 = z; F4 = w; } }"; comp = CreateCompilation(sourceB, references: new[] { AsReference(comp, useCompilationReference) }, parseOptions: useLatest ? TestOptions.Regular9 : TestOptions.Regular8, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); var verifier = CompileAndVerify(comp, verify: Verification.FailsPEVerify); verifier.VerifyIL("B.M1", @"{ // Code size 59 (0x3b) .maxstack 1 .locals init (nint? V_0, nuint? V_1) IL_0000: ldsfld ""nint A.F1"" IL_0005: pop IL_0006: ldsfld ""nuint A.F2"" IL_000b: pop IL_000c: ldsfld ""nint? A.F3"" IL_0011: stloc.0 IL_0012: ldloca.s V_0 IL_0014: call ""readonly bool nint?.HasValue.get"" IL_0019: brfalse.s IL_0023 IL_001b: ldloca.s V_0 IL_001d: call ""readonly nint nint?.GetValueOrDefault()"" IL_0022: pop IL_0023: ldsfld ""nuint? A.F4"" IL_0028: stloc.1 IL_0029: ldloca.s V_1 IL_002b: call ""readonly bool nuint?.HasValue.get"" IL_0030: brfalse.s IL_003a IL_0032: ldloca.s V_1 IL_0034: call ""readonly nuint nuint?.GetValueOrDefault()"" IL_0039: pop IL_003a: ret }", ilFormat: ILFormat); verifier.VerifyIL("B.M2", @"{ // Code size 95 (0x5f) .maxstack 1 .locals init (int? V_0, nint? V_1, uint? V_2, nuint? V_3) IL_0000: ldarg.0 IL_0001: conv.i IL_0002: stsfld ""nint A.F1"" IL_0007: ldarg.1 IL_0008: conv.u IL_0009: stsfld ""nuint A.F2"" IL_000e: ldarg.2 IL_000f: stloc.0 IL_0010: ldloca.s V_0 IL_0012: call ""readonly bool int?.HasValue.get"" IL_0017: brtrue.s IL_0024 IL_0019: ldloca.s V_1 IL_001b: initobj ""nint?"" IL_0021: ldloc.1 IL_0022: br.s IL_0031 IL_0024: ldloca.s V_0 IL_0026: call ""readonly int int?.GetValueOrDefault()"" IL_002b: conv.i IL_002c: newobj ""nint?..ctor(nint)"" IL_0031: stsfld ""nint? A.F3"" IL_0036: ldarg.3 IL_0037: stloc.2 IL_0038: ldloca.s V_2 IL_003a: call ""readonly bool uint?.HasValue.get"" IL_003f: brtrue.s IL_004c IL_0041: ldloca.s V_3 IL_0043: initobj ""nuint?"" IL_0049: ldloc.3 IL_004a: br.s IL_0059 IL_004c: ldloca.s V_2 IL_004e: call ""readonly uint uint?.GetValueOrDefault()"" IL_0053: conv.u IL_0054: newobj ""nuint?..ctor(nuint)"" IL_0059: stsfld ""nuint? A.F4"" IL_005e: ret }", ilFormat: ILFormat); } [Theory, CombinatorialData] public void BuiltInOperators_NativeIntegers(bool useCSharp9, bool useCompilationReference, bool useSystemTypes) { var nintType = useSystemTypes ? "System.IntPtr" : "nint"; var nuintType = useSystemTypes ? "System.UIntPtr" : "nuint"; var sourceA = $$""" public class A { public static {{nintType}} F1; public static {{nuintType}} F2; public static {{nintType}}? F3; public static {{nuintType}}? F4; } """; var comp = CreateCompilation(sourceA, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); var refA = AsReference(comp, useCompilationReference); var sourceB = @"class B : A { static void Main() { F1 = -F1; F2 = +F2; F3 = -F3; F4 = +F4; F1 = F1 * F1; F2 = F2 / F2; F3 = F3 * F1; F4 = F4 / F2; } }"; comp = CreateCompilation(sourceB, references: new[] { refA }, parseOptions: useCSharp9 ? TestOptions.Regular9 : TestOptions.Regular8, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); var verifier = CompileAndVerify(comp, verify: Verification.FailsPEVerify); verifier.VerifyIL("B.Main", @"{ // Code size 247 (0xf7) .maxstack 2 .locals init (nint? V_0, nint? V_1, nuint? V_2, nuint? V_3, nint V_4, nuint V_5) IL_0000: ldsfld ""nint A.F1"" IL_0005: neg IL_0006: stsfld ""nint A.F1"" IL_000b: ldsfld ""nuint A.F2"" IL_0010: stsfld ""nuint A.F2"" IL_0015: ldsfld ""nint? A.F3"" IL_001a: stloc.0 IL_001b: ldloca.s V_0 IL_001d: call ""readonly bool nint?.HasValue.get"" IL_0022: brtrue.s IL_002f IL_0024: ldloca.s V_1 IL_0026: initobj ""nint?"" IL_002c: ldloc.1 IL_002d: br.s IL_003c IL_002f: ldloca.s V_0 IL_0031: call ""readonly nint nint?.GetValueOrDefault()"" IL_0036: neg IL_0037: newobj ""nint?..ctor(nint)"" IL_003c: stsfld ""nint? A.F3"" IL_0041: ldsfld ""nuint? A.F4"" IL_0046: stloc.2 IL_0047: ldloca.s V_2 IL_0049: call ""readonly bool nuint?.HasValue.get"" IL_004e: brtrue.s IL_005b IL_0050: ldloca.s V_3 IL_0052: initobj ""nuint?"" IL_0058: ldloc.3 IL_0059: br.s IL_0067 IL_005b: ldloca.s V_2 IL_005d: call ""readonly nuint nuint?.GetValueOrDefault()"" IL_0062: newobj ""nuint?..ctor(nuint)"" IL_0067: stsfld ""nuint? A.F4"" IL_006c: ldsfld ""nint A.F1"" IL_0071: ldsfld ""nint A.F1"" IL_0076: mul IL_0077: stsfld ""nint A.F1"" IL_007c: ldsfld ""nuint A.F2"" IL_0081: ldsfld ""nuint A.F2"" IL_0086: div.un IL_0087: stsfld ""nuint A.F2"" IL_008c: ldsfld ""nint? A.F3"" IL_0091: stloc.0 IL_0092: ldsfld ""nint A.F1"" IL_0097: stloc.s V_4 IL_0099: ldloca.s V_0 IL_009b: call ""readonly bool nint?.HasValue.get"" IL_00a0: brtrue.s IL_00ad IL_00a2: ldloca.s V_1 IL_00a4: initobj ""nint?"" IL_00aa: ldloc.1 IL_00ab: br.s IL_00bc IL_00ad: ldloca.s V_0 IL_00af: call ""readonly nint nint?.GetValueOrDefault()"" IL_00b4: ldloc.s V_4 IL_00b6: mul IL_00b7: newobj ""nint?..ctor(nint)"" IL_00bc: stsfld ""nint? A.F3"" IL_00c1: ldsfld ""nuint? A.F4"" IL_00c6: stloc.2 IL_00c7: ldsfld ""nuint A.F2"" IL_00cc: stloc.s V_5 IL_00ce: ldloca.s V_2 IL_00d0: call ""readonly bool nuint?.HasValue.get"" IL_00d5: brtrue.s IL_00e2 IL_00d7: ldloca.s V_3 IL_00d9: initobj ""nuint?"" IL_00df: ldloc.3 IL_00e0: br.s IL_00f1 IL_00e2: ldloca.s V_2 IL_00e4: call ""readonly nuint nuint?.GetValueOrDefault()"" IL_00e9: ldloc.s V_5 IL_00eb: div.un IL_00ec: newobj ""nuint?..ctor(nuint)"" IL_00f1: stsfld ""nuint? A.F4"" IL_00f6: ret }", ilFormat: ILFormat); } [Fact, WorkItem(63860, "https://github.com/dotnet/roslyn/issues/63860")] public void IntPtrOperator_OnPlatformWithNumericIntPtr() { var source = """ using System; class C { public static void M() { IntPtr a = default; bool b = a == IntPtr.Zero; a += 1; _ = a + 1; } } """; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); } [Fact, WorkItem(63860, "https://github.com/dotnet/roslyn/issues/63860")] public void IntPtrOperator_OnPlatformWithoutNumericIntPtr() { var source = """ using System; class C { public static void M() { IntPtr a = default; bool b = a == IntPtr.Zero; a += 1; _ = a + 1; } } """; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular7_3); comp.VerifyDiagnostics(); comp = CreateCompilation(source); comp.VerifyDiagnostics(); } [Theory] [CombinatorialData] public void SemanticModel_UnaryOperators(bool lifted) { string typeQualifier = lifted ? "?" : ""; var source = $@"class Program {{ static void F(nint{typeQualifier} x, nuint{typeQualifier} y) {{ _ = +x; _ = -x; _ = ~x; _ = +y; _ = ~y; }} }}"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics(); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var nodes = tree.GetRoot().DescendantNodes().OfType<PrefixUnaryExpressionSyntax>(); var actualOperators = nodes.Select(n => model.GetSymbolInfo(n).Symbol.ToDisplayString(TestFormat)).ToArray(); var expectedOperators = new[] { "nint nint.op_UnaryPlus(nint value)", "nint nint.op_UnaryNegation(nint value)", "nint nint.op_OnesComplement(nint value)", "nuint nuint.op_UnaryPlus(nuint value)", "nuint nuint.op_OnesComplement(nuint value)", }; AssertEx.Equal(expectedOperators, actualOperators); } [Theory] [InlineData("nint", false)] [InlineData("nuint", false)] [InlineData("nint", true)] [InlineData("nuint", true)] [InlineData("System.IntPtr", false)] [InlineData("System.UIntPtr", false)] [InlineData("System.IntPtr", true)] [InlineData("System.UIntPtr", true)] public void SemanticModel_BinaryOperators(string type, bool lifted) { string typeQualifier = lifted ? "?" : ""; var source = $@"class Program {{ static void F({type}{typeQualifier} x, {type}{typeQualifier} y) {{ _ = x + y; _ = x - y; _ = x * y; _ = x / y; _ = x % y; _ = x < y; _ = x <= y; _ = x > y; _ = x >= y; _ = x == y; _ = x != y; _ = x & y; _ = x | y; _ = x ^ y; _ = x << 1; _ = x >> 1; }} }}"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics(); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var nodes = tree.GetRoot().DescendantNodes().OfType<BinaryExpressionSyntax>(); var actualOperators = nodes.Select(n => model.GetSymbolInfo(n).Symbol.ToDisplayString(TestFormat)).ToArray(); var nativeType = AsNative(type); var expectedOperators = new[] { $"{nativeType} {nativeType}.op_Addition({nativeType} left, {nativeType} right)", $"{nativeType} {nativeType}.op_Subtraction({nativeType} left, {nativeType} right)", $"{nativeType} {nativeType}.op_Multiply({nativeType} left, {nativeType} right)", $"{nativeType} {nativeType}.op_Division({nativeType} left, {nativeType} right)", $"{nativeType} {nativeType}.op_Modulus({nativeType} left, {nativeType} right)", $"System.Boolean {nativeType}.op_LessThan({nativeType} left, {nativeType} right)", $"System.Boolean {nativeType}.op_LessThanOrEqual({nativeType} left, {nativeType} right)", $"System.Boolean {nativeType}.op_GreaterThan({nativeType} left, {nativeType} right)", $"System.Boolean {nativeType}.op_GreaterThanOrEqual({nativeType} left, {nativeType} right)", $"System.Boolean {nativeType}.op_Equality({nativeType} left, {nativeType} right)", $"System.Boolean {nativeType}.op_Inequality({nativeType} left, {nativeType} right)", $"{nativeType} {nativeType}.op_BitwiseAnd({nativeType} left, {nativeType} right)", $"{nativeType} {nativeType}.op_BitwiseOr({nativeType} left, {nativeType} right)", $"{nativeType} {nativeType}.op_ExclusiveOr({nativeType} left, {nativeType} right)", $"{nativeType} {nativeType}.op_LeftShift({nativeType} left, System.Int32 right)", $"{nativeType} {nativeType}.op_RightShift({nativeType} left, System.Int32 right)", }; AssertEx.Equal(expectedOperators, actualOperators); } [Theory] [InlineData("")] [InlineData("unchecked")] [InlineData("checked")] public void ConstantConversions_ToNativeInt(string context) { var source = $@"#pragma warning disable 219 class Program {{ static void F1() {{ System.IntPtr i; {context} {{ i = sbyte.MaxValue; i = byte.MaxValue; i = char.MaxValue; i = short.MaxValue; i = ushort.MaxValue; i = int.MaxValue; i = uint.MaxValue; i = long.MaxValue; i = ulong.MaxValue; i = float.MaxValue; i = double.MaxValue; i = (decimal)int.MaxValue; i = (nint)int.MaxValue; i = (nuint)uint.MaxValue; }} }} static void F2() {{ System.UIntPtr u; {context} {{ u = sbyte.MaxValue; u = byte.MaxValue; u = char.MaxValue; u = short.MaxValue; u = ushort.MaxValue; u = int.MaxValue; u = uint.MaxValue; u = long.MaxValue; u = ulong.MaxValue; u = float.MaxValue; u = double.MaxValue; u = (decimal)uint.MaxValue; u = (nint)int.MaxValue; u = (nuint)uint.MaxValue; }} }} }}"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics( // (15,17): error CS0266: Cannot implicitly convert type 'uint' to 'nint'. An explicit conversion exists (are you missing a cast?) // i = uint.MaxValue; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "uint.MaxValue").WithArguments("uint", "nint").WithLocation(15, 17), // (16,17): error CS0266: Cannot implicitly convert type 'long' to 'nint'. An explicit conversion exists (are you missing a cast?) // i = long.MaxValue; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "long.MaxValue").WithArguments("long", "nint").WithLocation(16, 17), // (17,17): error CS0266: Cannot implicitly convert type 'ulong' to 'nint'. An explicit conversion exists (are you missing a cast?) // i = ulong.MaxValue; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "ulong.MaxValue").WithArguments("ulong", "nint").WithLocation(17, 17), // (18,17): error CS0266: Cannot implicitly convert type 'float' to 'nint'. An explicit conversion exists (are you missing a cast?) // i = float.MaxValue; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "float.MaxValue").WithArguments("float", "nint").WithLocation(18, 17), // (19,17): error CS0266: Cannot implicitly convert type 'double' to 'nint'. An explicit conversion exists (are you missing a cast?) // i = double.MaxValue; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "double.MaxValue").WithArguments("double", "nint").WithLocation(19, 17), // (20,17): error CS0266: Cannot implicitly convert type 'decimal' to 'nint'. An explicit conversion exists (are you missing a cast?) // i = (decimal)int.MaxValue; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "(decimal)int.MaxValue").WithArguments("decimal", "nint").WithLocation(20, 17), // (22,17): error CS0266: Cannot implicitly convert type 'nuint' to 'nint'. An explicit conversion exists (are you missing a cast?) // i = (nuint)uint.MaxValue; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "(nuint)uint.MaxValue").WithArguments("nuint", "nint").WithLocation(22, 17), // (30,17): error CS0266: Cannot implicitly convert type 'sbyte' to 'nuint'. An explicit conversion exists (are you missing a cast?) // u = sbyte.MaxValue; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "sbyte.MaxValue").WithArguments("sbyte", "nuint").WithLocation(30, 17), // (33,17): error CS0266: Cannot implicitly convert type 'short' to 'nuint'. An explicit conversion exists (are you missing a cast?) // u = short.MaxValue; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "short.MaxValue").WithArguments("short", "nuint").WithLocation(33, 17), // (37,17): error CS0266: Cannot implicitly convert type 'long' to 'nuint'. An explicit conversion exists (are you missing a cast?) // u = long.MaxValue; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "long.MaxValue").WithArguments("long", "nuint").WithLocation(37, 17), // (38,17): error CS0266: Cannot implicitly convert type 'ulong' to 'nuint'. An explicit conversion exists (are you missing a cast?) // u = ulong.MaxValue; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "ulong.MaxValue").WithArguments("ulong", "nuint").WithLocation(38, 17), // (39,17): error CS0266: Cannot implicitly convert type 'float' to 'nuint'. An explicit conversion exists (are you missing a cast?) // u = float.MaxValue; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "float.MaxValue").WithArguments("float", "nuint").WithLocation(39, 17), // (40,17): error CS0266: Cannot implicitly convert type 'double' to 'nuint'. An explicit conversion exists (are you missing a cast?) // u = double.MaxValue; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "double.MaxValue").WithArguments("double", "nuint").WithLocation(40, 17), // (41,17): error CS0266: Cannot implicitly convert type 'decimal' to 'nuint'. An explicit conversion exists (are you missing a cast?) // u = (decimal)uint.MaxValue; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "(decimal)uint.MaxValue").WithArguments("decimal", "nuint").WithLocation(41, 17), // (42,17): error CS0266: Cannot implicitly convert type 'nint' to 'nuint'. An explicit conversion exists (are you missing a cast?) // u = (nint)int.MaxValue; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "(nint)int.MaxValue").WithArguments("nint", "nuint").WithLocation(42, 17)); } [Theory] [InlineData("")] [InlineData("unchecked")] [InlineData("checked")] public void ConstantConversions_FromNativeInt(string context) { var source = $@"#pragma warning disable 219 class Program {{ static void F1() {{ const System.IntPtr n = (System.IntPtr)int.MaxValue; {context} {{ sbyte sb = n; byte b = n; char c = n; short s = n; ushort us = n; int i = n; uint u = n; long l = n; ulong ul = n; float f = n; double d = n; decimal dec = n; nuint nu = n; }} }} static void F2() {{ const System.UIntPtr nu = (System.UIntPtr)uint.MaxValue; {context} {{ sbyte sb = nu; byte b = nu; char c = nu; short s = nu; ushort us = nu; int i = nu; uint u = nu; long l = nu; ulong ul = nu; float f = nu; double d = nu; decimal dec = nu; nint n = nu; }} }} }}"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics( // (9,24): error CS0266: Cannot implicitly convert type 'nint' to 'sbyte'. An explicit conversion exists (are you missing a cast?) // sbyte sb = n; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "n").WithArguments("nint", "sbyte").WithLocation(9, 24), // (10,22): error CS0266: Cannot implicitly convert type 'nint' to 'byte'. An explicit conversion exists (are you missing a cast?) // byte b = n; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "n").WithArguments("nint", "byte").WithLocation(10, 22), // (11,22): error CS0266: Cannot implicitly convert type 'nint' to 'char'. An explicit conversion exists (are you missing a cast?) // char c = n; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "n").WithArguments("nint", "char").WithLocation(11, 22), // (12,23): error CS0266: Cannot implicitly convert type 'nint' to 'short'. An explicit conversion exists (are you missing a cast?) // short s = n; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "n").WithArguments("nint", "short").WithLocation(12, 23), // (13,25): error CS0266: Cannot implicitly convert type 'nint' to 'ushort'. An explicit conversion exists (are you missing a cast?) // ushort us = n; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "n").WithArguments("nint", "ushort").WithLocation(13, 25), // (14,21): error CS0266: Cannot implicitly convert type 'nint' to 'int'. An explicit conversion exists (are you missing a cast?) // int i = n; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "n").WithArguments("nint", "int").WithLocation(14, 21), // (15,22): error CS0266: Cannot implicitly convert type 'nint' to 'uint'. An explicit conversion exists (are you missing a cast?) // uint u = n; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "n").WithArguments("nint", "uint").WithLocation(15, 22), // (17,24): error CS0266: Cannot implicitly convert type 'nint' to 'ulong'. An explicit conversion exists (are you missing a cast?) // ulong ul = n; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "n").WithArguments("nint", "ulong").WithLocation(17, 24), // (21,24): error CS0266: Cannot implicitly convert type 'nint' to 'nuint'. An explicit conversion exists (are you missing a cast?) // nuint nu = n; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "n").WithArguments("nint", "nuint").WithLocation(21, 24), // (29,24): error CS0266: Cannot implicitly convert type 'nuint' to 'sbyte'. An explicit conversion exists (are you missing a cast?) // sbyte sb = nu; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "nu").WithArguments("nuint", "sbyte").WithLocation(29, 24), // (30,22): error CS0266: Cannot implicitly convert type 'nuint' to 'byte'. An explicit conversion exists (are you missing a cast?) // byte b = nu; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "nu").WithArguments("nuint", "byte").WithLocation(30, 22), // (31,22): error CS0266: Cannot implicitly convert type 'nuint' to 'char'. An explicit conversion exists (are you missing a cast?) // char c = nu; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "nu").WithArguments("nuint", "char").WithLocation(31, 22), // (32,23): error CS0266: Cannot implicitly convert type 'nuint' to 'short'. An explicit conversion exists (are you missing a cast?) // short s = nu; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "nu").WithArguments("nuint", "short").WithLocation(32, 23), // (33,25): error CS0266: Cannot implicitly convert type 'nuint' to 'ushort'. An explicit conversion exists (are you missing a cast?) // ushort us = nu; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "nu").WithArguments("nuint", "ushort").WithLocation(33, 25), // (34,21): error CS0266: Cannot implicitly convert type 'nuint' to 'int'. An explicit conversion exists (are you missing a cast?) // int i = nu; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "nu").WithArguments("nuint", "int").WithLocation(34, 21), // (35,22): error CS0266: Cannot implicitly convert type 'nuint' to 'uint'. An explicit conversion exists (are you missing a cast?) // uint u = nu; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "nu").WithArguments("nuint", "uint").WithLocation(35, 22), // (36,22): error CS0266: Cannot implicitly convert type 'nuint' to 'long'. An explicit conversion exists (are you missing a cast?) // long l = nu; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "nu").WithArguments("nuint", "long").WithLocation(36, 22), // (41,22): error CS0266: Cannot implicitly convert type 'nuint' to 'nint'. An explicit conversion exists (are you missing a cast?) // nint n = nu; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "nu").WithArguments("nuint", "nint").WithLocation(41, 22)); } [Fact] public void ConstantConversions_01() { var source = @"using System; class Program { static void Main() { const long x = 0xFFFFFFFFFFFFFFFL; const IntPtr y = checked((IntPtr)x); Console.WriteLine(y); } }"; var comp = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics( // (7,26): error CS0133: The expression being assigned to 'y' must be constant // const IntPtr y = checked((IntPtr)x); Diagnostic(ErrorCode.ERR_NotConstantExpression, "checked((IntPtr)x)").WithArguments("y").WithLocation(7, 26), // (7,34): warning CS8778: Constant value '1152921504606846975' may overflow 'nint' at runtime (use 'unchecked' syntax to override) // const IntPtr y = checked((IntPtr)x); Diagnostic(ErrorCode.WRN_ConstOutOfRangeChecked, "(IntPtr)x").WithArguments("1152921504606846975", "nint").WithLocation(7, 34)); source = @"using System; class Program { static void Main() { const long x = 0xFFFFFFFFFFFFFFFL; try { nint y = checked((nint)x); Console.WriteLine(y); } catch (Exception e) { Console.WriteLine(e.GetType()); } } }"; comp = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics( // (9,30): warning CS8778: Constant value '1152921504606846975' may overflow 'nint' at runtime (use 'unchecked' syntax to override) // nint y = checked((nint)x); Diagnostic(ErrorCode.WRN_ConstOutOfRangeChecked, "(nint)x").WithArguments("1152921504606846975", "nint").WithLocation(9, 30)); CompileAndVerify(comp, expectedOutput: IncludeExpectedOutput(IntPtr.Size == 4 ? "System.OverflowException" : "1152921504606846975"), verify: Verification.FailsPEVerify); } [WorkItem(45531, "https://github.com/dotnet/roslyn/issues/45531")] [Fact] public void ConstantConversions_02() { var source = @"using System; class Program { static void Main() { const long x = 0xFFFFFFFFFFFFFFFL; const IntPtr y = unchecked((IntPtr)x); Console.WriteLine(y); } }"; var comp = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics( // (7,26): error CS0133: The expression being assigned to 'y' must be constant // const IntPtr y = unchecked((IntPtr)x); Diagnostic(ErrorCode.ERR_NotConstantExpression, "unchecked((IntPtr)x)").WithArguments("y").WithLocation(7, 26)); source = @"using System; class Program { static void Main() { const long x = 0xFFFFFFFFFFFFFFFL; IntPtr y = unchecked((IntPtr)x); Console.WriteLine(y); } }"; comp = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); CompileAndVerify(comp, verify: Verification.FailsPEVerify, expectedOutput: IncludeExpectedOutput(IntPtr.Size == 4 ? "-1" : "1152921504606846975")); } [Fact] public void ConstantConversions_03() { using var _ = new EnsureInvariantCulture(); constantConversions("sbyte", "IntPtr", "-1", null, "-1", "-1", null, "-1", "-1"); constantConversions("sbyte", "IntPtr", "sbyte.MinValue", null, "-128", "-128", null, "-128", "-128"); constantConversions("sbyte", "IntPtr", "sbyte.MaxValue", null, "127", "127", null, "127", "127"); constantConversions("byte", "IntPtr", "byte.MaxValue", null, "255", "255", null, "255", "255"); constantConversions("short", "IntPtr", "-1", null, "-1", "-1", null, "-1", "-1"); constantConversions("short", "IntPtr", "short.MinValue", null, "-32768", "-32768", null, "-32768", "-32768"); constantConversions("short", "IntPtr", "short.MaxValue", null, "32767", "32767", null, "32767", "32767"); constantConversions("ushort", "IntPtr", "ushort.MaxValue", null, "65535", "65535", null, "65535", "65535"); constantConversions("char", "IntPtr", "char.MaxValue", null, "65535", "65535", null, "65535", "65535"); constantConversions("int", "IntPtr", "int.MinValue", null, "-2147483648", "-2147483648", null, "-2147483648", "-2147483648"); constantConversions("int", "IntPtr", "int.MaxValue", null, "2147483647", "2147483647", null, "2147483647", "2147483647"); constantConversions("uint", "IntPtr", "(int.MaxValue + 1U)", warningOutOfRangeChecked("IntPtr", "2147483648"), "System.OverflowException", "2147483648", null, "-2147483648", "2147483648"); constantConversions("uint", "IntPtr", "uint.MaxValue", warningOutOfRangeChecked("IntPtr", "4294967295"), "System.OverflowException", "4294967295", null, "-1", "4294967295"); constantConversions("long", "IntPtr", "(int.MinValue - 1L)", warningOutOfRangeChecked("IntPtr", "-2147483649"), "System.OverflowException", "-2147483649", null, "2147483647", "-2147483649"); constantConversions("long", "IntPtr", "(int.MaxValue + 1L)", warningOutOfRangeChecked("IntPtr", "2147483648"), "System.OverflowException", "2147483648", null, "-2147483648", "2147483648"); constantConversions("long", "IntPtr", "long.MinValue", warningOutOfRangeChecked("IntPtr", "-9223372036854775808"), "System.OverflowException", "-9223372036854775808", null, "0", "-9223372036854775808"); constantConversions("long", "IntPtr", "long.MaxValue", warningOutOfRangeChecked("IntPtr", "9223372036854775807"), "System.OverflowException", "9223372036854775807", null, "-1", "9223372036854775807"); constantConversions("ulong", "IntPtr", "(int.MaxValue + 1UL)", warningOutOfRangeChecked("IntPtr", "2147483648"), "System.OverflowException", "2147483648", null, "-2147483648", "2147483648"); constantConversions("ulong", "IntPtr", "ulong.MaxValue", errorOutOfRangeChecked("IntPtr", "18446744073709551615"), "System.OverflowException", "System.OverflowException", null, "-1", "-1"); constantConversions("decimal", "IntPtr", "(int.MinValue - 1M)", errorOutOfRange("IntPtr", "-2147483649M"), "System.OverflowException", "-2147483649", errorOutOfRange("IntPtr", "-2147483649M"), "2147483647", "-2147483649"); constantConversions("decimal", "IntPtr", "(int.MaxValue + 1M)", errorOutOfRange("IntPtr", "2147483648M"), "System.OverflowException", "2147483648", errorOutOfRange("IntPtr", "2147483648M"), "-2147483648", "2147483648"); constantConversions("decimal", "IntPtr", "decimal.MinValue", errorOutOfRange("IntPtr", "-79228162514264337593543950335M"), "System.OverflowException", "System.OverflowException", errorOutOfRange("IntPtr", "-79228162514264337593543950335M"), "-1", "-1"); constantConversions("decimal", "IntPtr", "decimal.MaxValue", errorOutOfRange("IntPtr", "79228162514264337593543950335M"), "System.OverflowException", "System.OverflowException", errorOutOfRange("IntPtr", "79228162514264337593543950335M"), "-1", "-1"); constantConversions("IntPtr", "IntPtr", "int.MinValue", null, "-2147483648", "-2147483648", null, "-2147483648", "-2147483648"); constantConversions("IntPtr", "IntPtr", "int.MaxValue", null, "2147483647", "2147483647", null, "2147483647", "2147483647"); constantConversions("UIntPtr", "IntPtr", "(int.MaxValue + (nuint)1)", warningOutOfRangeChecked("IntPtr", "2147483648"), "System.OverflowException", "2147483648", null, "-2147483648", "2147483648"); constantConversions("sbyte", "UIntPtr", "-1", errorOutOfRangeChecked("UIntPtr", "-1"), "System.OverflowException", "System.OverflowException", null, "4294967295", "18446744073709551615"); constantConversions("sbyte", "UIntPtr", "sbyte.MinValue", errorOutOfRangeChecked("UIntPtr", "-128"), "System.OverflowException", "System.OverflowException", null, "4294967168", "18446744073709551488"); constantConversions("sbyte", "UIntPtr", "sbyte.MaxValue", null, "127", "127", null, "127", "127"); constantConversions("byte", "UIntPtr", "byte.MaxValue", null, "255", "255", null, "255", "255"); constantConversions("short", "UIntPtr", "-1", errorOutOfRangeChecked("UIntPtr", "-1"), "System.OverflowException", "System.OverflowException", null, "4294967295", "18446744073709551615"); constantConversions("short", "UIntPtr", "short.MinValue", errorOutOfRangeChecked("UIntPtr", "-32768"), "System.OverflowException", "System.OverflowException", null, "4294934528", "18446744073709518848"); constantConversions("short", "UIntPtr", "short.MaxValue", null, "32767", "32767", null, "32767", "32767"); constantConversions("ushort", "UIntPtr", "ushort.MaxValue", null, "65535", "65535", null, "65535", "65535"); constantConversions("char", "UIntPtr", "char.MaxValue", null, "65535", "65535", null, "65535", "65535"); constantConversions("int", "UIntPtr", "-1", errorOutOfRangeChecked("UIntPtr", "-1"), "System.OverflowException", "System.OverflowException", null, "4294967295", "18446744073709551615"); constantConversions("int", "UIntPtr", "int.MinValue", errorOutOfRangeChecked("UIntPtr", "-2147483648"), "System.OverflowException", "System.OverflowException", null, "2147483648", "18446744071562067968"); constantConversions("int", "UIntPtr", "int.MaxValue", null, "2147483647", "2147483647", null, "2147483647", "2147483647"); constantConversions("uint", "UIntPtr", "uint.MaxValue", null, "4294967295", "4294967295", null, "4294967295", "4294967295"); constantConversions("long", "UIntPtr", "-1", errorOutOfRangeChecked("UIntPtr", "-1"), "System.OverflowException", "System.OverflowException", null, "4294967295", "18446744073709551615"); constantConversions("long", "UIntPtr", "uint.MaxValue + 1L", warningOutOfRangeChecked("UIntPtr", "4294967296"), "System.OverflowException", "4294967296", null, "0", "4294967296"); constantConversions("long", "UIntPtr", "long.MinValue", errorOutOfRangeChecked("UIntPtr", "-9223372036854775808"), "System.OverflowException", "System.OverflowException", null, "0", "9223372036854775808"); constantConversions("long", "UIntPtr", "long.MaxValue", warningOutOfRangeChecked("UIntPtr", "9223372036854775807"), "System.OverflowException", "9223372036854775807", null, "4294967295", "9223372036854775807"); constantConversions("ulong", "UIntPtr", "uint.MaxValue + 1UL", warningOutOfRangeChecked("UIntPtr", "4294967296"), "System.OverflowException", "4294967296", null, "0", "4294967296"); constantConversions("ulong", "UIntPtr", "ulong.MaxValue", warningOutOfRangeChecked("UIntPtr", "18446744073709551615"), "System.OverflowException", "18446744073709551615", null, "4294967295", "18446744073709551615"); constantConversions("decimal", "UIntPtr", "-1", errorOutOfRange("UIntPtr", "-1M"), "System.OverflowException", "System.OverflowException", errorOutOfRange("UIntPtr", "-1M"), "System.OverflowException", "System.OverflowException"); constantConversions("decimal", "UIntPtr", "(uint.MaxValue + 1M)", errorOutOfRange("UIntPtr", "4294967296M"), "System.OverflowException", "4294967296", errorOutOfRange("UIntPtr", "4294967296M"), "-1", "4294967296"); constantConversions("decimal", "UIntPtr", "decimal.MinValue", errorOutOfRange("UIntPtr", "-79228162514264337593543950335M"), "System.OverflowException", "System.OverflowException", errorOutOfRange("UIntPtr", "-79228162514264337593543950335M"), "-1", "-1"); constantConversions("decimal", "UIntPtr", "decimal.MaxValue", errorOutOfRange("UIntPtr", "79228162514264337593543950335M"), "System.OverflowException", "System.OverflowException", errorOutOfRange("UIntPtr", "79228162514264337593543950335M"), "-1", "-1"); constantConversions("IntPtr", "UIntPtr", "-1", errorOutOfRangeChecked("UIntPtr", "-1"), "System.OverflowException", "System.OverflowException", null, "4294967295", "18446744073709551615"); constantConversions("UIntPtr", "UIntPtr", "uint.MaxValue", null, "4294967295", "4294967295", null, "4294967295", "4294967295"); if (!ExecutionConditionUtil.IsWindowsDesktop) { // There are differences in floating point precision across platforms // so floating point tests are limited to one platform. return; } constantConversions("float", "IntPtr", "(int.MinValue - 10000F)", warningOutOfRangeChecked("IntPtr", "-2.147494E+09"), "System.OverflowException", "-2147493632", null, "-2147483648", "-2147493632"); constantConversions("float", "IntPtr", "(int.MaxValue + 10000F)", warningOutOfRangeChecked("IntPtr", "2.147494E+09"), "System.OverflowException", "2147493632", null, "-2147483648", "2147493632"); constantConversions("float", "IntPtr", "float.MinValue", errorOutOfRangeChecked("IntPtr", "-3.402823E+38"), "System.OverflowException", "System.OverflowException", null, "-2147483648", "-9223372036854775808"); constantConversions("float", "IntPtr", "float.MaxValue", errorOutOfRangeChecked("IntPtr", "3.402823E+38"), "System.OverflowException", "System.OverflowException", null, "-2147483648", "-9223372036854775808"); constantConversions("double", "IntPtr", "(int.MinValue - 1D)", warningOutOfRangeChecked("IntPtr", "-2147483649"), "System.OverflowException", "-2147483649", null, "-2147483648", "-2147483649"); constantConversions("double", "IntPtr", "(int.MaxValue + 1D)", warningOutOfRangeChecked("IntPtr", "2147483648"), "System.OverflowException", "2147483648", null, "-2147483648", "2147483648"); constantConversions("double", "IntPtr", "double.MinValue", errorOutOfRangeChecked("IntPtr", "-1.79769313486232E+308"), "System.OverflowException", "System.OverflowException", null, "-2147483648", "-9223372036854775808"); constantConversions("double", "IntPtr", "double.MaxValue", errorOutOfRangeChecked("IntPtr", "1.79769313486232E+308"), "System.OverflowException", "System.OverflowException", null, "-2147483648", "-9223372036854775808"); constantConversions("float", "UIntPtr", "-1", errorOutOfRangeChecked("UIntPtr", "-1"), "System.OverflowException", "System.OverflowException", null, "4294967295", "18446744073709551615"); constantConversions("float", "UIntPtr", "(uint.MaxValue + 1F)", warningOutOfRangeChecked("UIntPtr", "4.294967E+09"), "System.OverflowException", "4294967296", null, "0", "4294967296"); constantConversions("float", "UIntPtr", "float.MinValue", errorOutOfRangeChecked("UIntPtr", "-3.402823E+38"), "System.OverflowException", "System.OverflowException", null, "0", "9223372036854775808"); constantConversions("float", "UIntPtr", "float.MaxValue", errorOutOfRangeChecked("UIntPtr", "3.402823E+38"), "System.OverflowException", "System.OverflowException", null, "0", "0"); constantConversions("double", "UIntPtr", "-1", errorOutOfRangeChecked("UIntPtr", "-1"), "System.OverflowException", "System.OverflowException", null, "4294967295", "18446744073709551615"); constantConversions("double", "UIntPtr", "(uint.MaxValue + 1D)", warningOutOfRangeChecked("UIntPtr", "4294967296"), "System.OverflowException", "4294967296", null, "0", "4294967296"); constantConversions("double", "UIntPtr", "double.MinValue", errorOutOfRangeChecked("UIntPtr", "-1.79769313486232E+308"), "System.OverflowException", "System.OverflowException", null, "0", "9223372036854775808"); constantConversions("double", "UIntPtr", "double.MaxValue", errorOutOfRangeChecked("UIntPtr", "1.79769313486232E+308"), "System.OverflowException", "System.OverflowException", null, "0", "0"); static DiagnosticDescription errorOutOfRangeChecked(string destinationType, string value) => Diagnostic(ErrorCode.ERR_ConstOutOfRangeChecked, $"({destinationType})x").WithArguments(value, AsNative(destinationType)); static DiagnosticDescription errorOutOfRange(string destinationType, string value) => Diagnostic(ErrorCode.ERR_ConstOutOfRange, $"({destinationType})x").WithArguments(value, AsNative(destinationType)); static DiagnosticDescription warningOutOfRangeChecked(string destinationType, string value) => Diagnostic(ErrorCode.WRN_ConstOutOfRangeChecked, $"({destinationType})x").WithArguments(value, AsNative(destinationType)); void constantConversions(string sourceType, string destinationType, string sourceValue, DiagnosticDescription checkedError, string checked32, string checked64, DiagnosticDescription uncheckedError, string unchecked32, string unchecked64) { constantConversion(sourceType, destinationType, sourceValue, useChecked: true, checkedError, IntPtr.Size == 4 ? checked32 : checked64); constantConversion(sourceType, destinationType, sourceValue, useChecked: false, uncheckedError, IntPtr.Size == 4 ? unchecked32 : unchecked64); } void constantConversion(string sourceType, string destinationType, string sourceValue, bool useChecked, DiagnosticDescription expectedError, string expectedOutput) { var source = $@"using System; class Program {{ static void Main() {{ const {sourceType} x = {sourceValue}; object y; try {{ y = {(useChecked ? "checked" : "unchecked")}(({destinationType})x); }} catch (Exception e) {{ y = e.GetType(); }} Console.Write(y); }} }}"; var comp = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(expectedError is null ? Array.Empty<DiagnosticDescription>() : new[] { expectedError }); if (expectedError == null || ErrorFacts.IsWarning((ErrorCode)expectedError.Code)) { CompileAndVerify(comp, verify: Verification.FailsPEVerify, expectedOutput: IncludeExpectedOutput(expectedOutput)); } } } [Theory] [InlineData("nint")] [InlineData("System.IntPtr")] public void Constants_NInt(string type) { string source = $@"class Program {{ static void Main() {{ F(default); F(int.MinValue); F({short.MinValue - 1}); F(short.MinValue); F(sbyte.MinValue); F(-2); F(-1); F(0); F(1); F(2); F(3); F(4); F(5); F(6); F(7); F(8); F(9); F(sbyte.MaxValue); F(byte.MaxValue); F(short.MaxValue); F(char.MaxValue); F(ushort.MaxValue); F({ushort.MaxValue + 1}); F(int.MaxValue); }} static void F({type} n) {{ System.Console.WriteLine(n); }} }}"; var comp = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); string expectedOutput = @"0 -2147483648 -32769 -32768 -128 -2 -1 0 1 2 3 4 5 6 7 8 9 127 255 32767 65535 65535 65536 2147483647"; var verifier = CompileAndVerify(comp, expectedOutput: IncludeExpectedOutput(expectedOutput), verify: Verification.FailsPEVerify); string expectedIL = @"{ // Code size 209 (0xd1) .maxstack 1 IL_0000: ldc.i4.0 IL_0001: conv.i IL_0002: call ""void Program.F(nint)"" IL_0007: ldc.i4 0x80000000 IL_000c: conv.i IL_000d: call ""void Program.F(nint)"" IL_0012: ldc.i4 0xffff7fff IL_0017: conv.i IL_0018: call ""void Program.F(nint)"" IL_001d: ldc.i4 0xffff8000 IL_0022: conv.i IL_0023: call ""void Program.F(nint)"" IL_0028: ldc.i4.s -128 IL_002a: conv.i IL_002b: call ""void Program.F(nint)"" IL_0030: ldc.i4.s -2 IL_0032: conv.i IL_0033: call ""void Program.F(nint)"" IL_0038: ldc.i4.m1 IL_0039: conv.i IL_003a: call ""void Program.F(nint)"" IL_003f: ldc.i4.0 IL_0040: conv.i IL_0041: call ""void Program.F(nint)"" IL_0046: ldc.i4.1 IL_0047: conv.i IL_0048: call ""void Program.F(nint)"" IL_004d: ldc.i4.2 IL_004e: conv.i IL_004f: call ""void Program.F(nint)"" IL_0054: ldc.i4.3 IL_0055: conv.i IL_0056: call ""void Program.F(nint)"" IL_005b: ldc.i4.4 IL_005c: conv.i IL_005d: call ""void Program.F(nint)"" IL_0062: ldc.i4.5 IL_0063: conv.i IL_0064: call ""void Program.F(nint)"" IL_0069: ldc.i4.6 IL_006a: conv.i IL_006b: call ""void Program.F(nint)"" IL_0070: ldc.i4.7 IL_0071: conv.i IL_0072: call ""void Program.F(nint)"" IL_0077: ldc.i4.8 IL_0078: conv.i IL_0079: call ""void Program.F(nint)"" IL_007e: ldc.i4.s 9 IL_0080: conv.i IL_0081: call ""void Program.F(nint)"" IL_0086: ldc.i4.s 127 IL_0088: conv.i IL_0089: call ""void Program.F(nint)"" IL_008e: ldc.i4 0xff IL_0093: conv.i IL_0094: call ""void Program.F(nint)"" IL_0099: ldc.i4 0x7fff IL_009e: conv.i IL_009f: call ""void Program.F(nint)"" IL_00a4: ldc.i4 0xffff IL_00a9: conv.i IL_00aa: call ""void Program.F(nint)"" IL_00af: ldc.i4 0xffff IL_00b4: conv.i IL_00b5: call ""void Program.F(nint)"" IL_00ba: ldc.i4 0x10000 IL_00bf: conv.i IL_00c0: call ""void Program.F(nint)"" IL_00c5: ldc.i4 0x7fffffff IL_00ca: conv.i IL_00cb: call ""void Program.F(nint)"" IL_00d0: ret }"; verifier.VerifyIL("Program.Main", expectedIL, ilFormat: ILFormat); } [Theory] [InlineData("nuint")] [InlineData("System.UIntPtr")] public void Constants_NUInt(string type) { string source = $@"class Program {{ static void Main() {{ F(default); F(0); F(1); F(2); F(3); F(4); F(5); F(6); F(7); F(8); F(9); F(byte.MaxValue); F(char.MaxValue); F(ushort.MaxValue); F(int.MaxValue); F({(uint)int.MaxValue + 1}); F(uint.MaxValue); }} static void F({type} n) {{ System.Console.WriteLine(n); }} }}"; var comp = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); string expectedOutput = @"0 0 1 2 3 4 5 6 7 8 9 255 65535 65535 2147483647 2147483648 4294967295"; var verifier = CompileAndVerify(comp, expectedOutput: IncludeExpectedOutput(expectedOutput), verify: Verification.FailsPEVerify); string expectedIL = @"{ // Code size 141 (0x8d) .maxstack 1 IL_0000: ldc.i4.0 IL_0001: conv.i IL_0002: call ""void Program.F(nuint)"" IL_0007: ldc.i4.0 IL_0008: conv.i IL_0009: call ""void Program.F(nuint)"" IL_000e: ldc.i4.1 IL_000f: conv.i IL_0010: call ""void Program.F(nuint)"" IL_0015: ldc.i4.2 IL_0016: conv.i IL_0017: call ""void Program.F(nuint)"" IL_001c: ldc.i4.3 IL_001d: conv.i IL_001e: call ""void Program.F(nuint)"" IL_0023: ldc.i4.4 IL_0024: conv.i IL_0025: call ""void Program.F(nuint)"" IL_002a: ldc.i4.5 IL_002b: conv.i IL_002c: call ""void Program.F(nuint)"" IL_0031: ldc.i4.6 IL_0032: conv.i IL_0033: call ""void Program.F(nuint)"" IL_0038: ldc.i4.7 IL_0039: conv.i IL_003a: call ""void Program.F(nuint)"" IL_003f: ldc.i4.8 IL_0040: conv.i IL_0041: call ""void Program.F(nuint)"" IL_0046: ldc.i4.s 9 IL_0048: conv.i IL_0049: call ""void Program.F(nuint)"" IL_004e: ldc.i4 0xff IL_0053: conv.i IL_0054: call ""void Program.F(nuint)"" IL_0059: ldc.i4 0xffff IL_005e: conv.i IL_005f: call ""void Program.F(nuint)"" IL_0064: ldc.i4 0xffff IL_0069: conv.i IL_006a: call ""void Program.F(nuint)"" IL_006f: ldc.i4 0x7fffffff IL_0074: conv.i IL_0075: call ""void Program.F(nuint)"" IL_007a: ldc.i4 0x80000000 IL_007f: conv.u IL_0080: call ""void Program.F(nuint)"" IL_0085: ldc.i4.m1 IL_0086: conv.u IL_0087: call ""void Program.F(nuint)"" IL_008c: ret }"; verifier.VerifyIL("Program.Main", expectedIL, ilFormat: ILFormat); } [Fact] public void Constants_ConvertToUnsigned() { string source = @"class Program { static void Main() { F<ushort>(sbyte.MaxValue); // 1 F<ushort>(short.MaxValue); // 2 F<ushort>(int.MaxValue); // 3 F<ushort>(long.MaxValue); // 4 F<uint>(sbyte.MaxValue); // 5 F<uint>(short.MaxValue); // 6 F<uint>(int.MaxValue); // 7 F<uint>(long.MaxValue); // 8 F<System.UIntPtr>(sbyte.MaxValue); // 9 F<System.UIntPtr>(short.MaxValue); // 10 F<System.UIntPtr>(int.MaxValue); // 11 F<System.UIntPtr>(long.MaxValue); // 12 F<nuint>(sbyte.MaxValue); // 13 F<nuint>(short.MaxValue); // 14 F<nuint>(int.MaxValue); // 15 F<nuint>(long.MaxValue); // 16 F<ulong>(sbyte.MaxValue); // 17 F<ulong>(short.MaxValue); // 18 F<ulong>(int.MaxValue); // 19 F<ulong>(long.MaxValue); // 20 } static void F<T>(T n) { } }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics( // (5,19): error CS1503: Argument 1: cannot convert from 'sbyte' to 'ushort' // F<ushort>(sbyte.MaxValue); // 1 Diagnostic(ErrorCode.ERR_BadArgType, "sbyte.MaxValue").WithArguments("1", "sbyte", "ushort").WithLocation(5, 19), // (6,19): error CS1503: Argument 1: cannot convert from 'short' to 'ushort' // F<ushort>(short.MaxValue); // 2 Diagnostic(ErrorCode.ERR_BadArgType, "short.MaxValue").WithArguments("1", "short", "ushort").WithLocation(6, 19), // (7,19): error CS1503: Argument 1: cannot convert from 'int' to 'ushort' // F<ushort>(int.MaxValue); // 3 Diagnostic(ErrorCode.ERR_BadArgType, "int.MaxValue").WithArguments("1", "int", "ushort").WithLocation(7, 19), // (8,19): error CS1503: Argument 1: cannot convert from 'long' to 'ushort' // F<ushort>(long.MaxValue); // 4 Diagnostic(ErrorCode.ERR_BadArgType, "long.MaxValue").WithArguments("1", "long", "ushort").WithLocation(8, 19), // (9,17): error CS1503: Argument 1: cannot convert from 'sbyte' to 'uint' // F<uint>(sbyte.MaxValue); // 5 Diagnostic(ErrorCode.ERR_BadArgType, "sbyte.MaxValue").WithArguments("1", "sbyte", "uint").WithLocation(9, 17), // (10,17): error CS1503: Argument 1: cannot convert from 'short' to 'uint' // F<uint>(short.MaxValue); // 6 Diagnostic(ErrorCode.ERR_BadArgType, "short.MaxValue").WithArguments("1", "short", "uint").WithLocation(10, 17), // (12,17): error CS1503: Argument 1: cannot convert from 'long' to 'uint' // F<uint>(long.MaxValue); // 8 Diagnostic(ErrorCode.ERR_BadArgType, "long.MaxValue").WithArguments("1", "long", "uint").WithLocation(12, 17), // (13,27): error CS1503: Argument 1: cannot convert from 'sbyte' to 'nuint' // F<System.UIntPtr>(sbyte.MaxValue); // 9 Diagnostic(ErrorCode.ERR_BadArgType, "sbyte.MaxValue").WithArguments("1", "sbyte", "nuint").WithLocation(13, 27), // (14,27): error CS1503: Argument 1: cannot convert from 'short' to 'nuint' // F<System.UIntPtr>(short.MaxValue); // 10 Diagnostic(ErrorCode.ERR_BadArgType, "short.MaxValue").WithArguments("1", "short", "nuint").WithLocation(14, 27), // (16,27): error CS1503: Argument 1: cannot convert from 'long' to 'nuint' // F<System.UIntPtr>(long.MaxValue); // 12 Diagnostic(ErrorCode.ERR_BadArgType, "long.MaxValue").WithArguments("1", "long", "nuint").WithLocation(16, 27), // (17,18): error CS1503: Argument 1: cannot convert from 'sbyte' to 'nuint' // F<nuint>(sbyte.MaxValue); // 13 Diagnostic(ErrorCode.ERR_BadArgType, "sbyte.MaxValue").WithArguments("1", "sbyte", "nuint").WithLocation(17, 18), // (18,18): error CS1503: Argument 1: cannot convert from 'short' to 'nuint' // F<nuint>(short.MaxValue); // 14 Diagnostic(ErrorCode.ERR_BadArgType, "short.MaxValue").WithArguments("1", "short", "nuint").WithLocation(18, 18), // (20,18): error CS1503: Argument 1: cannot convert from 'long' to 'nuint' // F<nuint>(long.MaxValue); // 16 Diagnostic(ErrorCode.ERR_BadArgType, "long.MaxValue").WithArguments("1", "long", "nuint").WithLocation(20, 18), // (21,18): error CS1503: Argument 1: cannot convert from 'sbyte' to 'ulong' // F<ulong>(sbyte.MaxValue); // 17 Diagnostic(ErrorCode.ERR_BadArgType, "sbyte.MaxValue").WithArguments("1", "sbyte", "ulong").WithLocation(21, 18), // (22,18): error CS1503: Argument 1: cannot convert from 'short' to 'ulong' // F<ulong>(short.MaxValue); // 18 Diagnostic(ErrorCode.ERR_BadArgType, "short.MaxValue").WithArguments("1", "short", "ulong").WithLocation(22, 18) ); } [Fact] public void Constants_Locals() { var source = @"#pragma warning disable 219 class Program { static void Main() { const System.IntPtr a = default; const nint b = default; const System.UIntPtr c = default; const nuint d = default; } }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); } [Fact] public void Constants_Fields_01() { var source = @"class Program { const System.IntPtr A = default(System.IntPtr); const nint B = default(nint); const System.UIntPtr C = default(System.UIntPtr); const nuint D = default(nuint); public static void Main() { System.Console.Write($""{A}, {B}, {C}, {D}""); } }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9, options: TestOptions.ReleaseExe, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); CompileAndVerify(comp, verify: Verification.FailsPEVerify, expectedOutput: IncludeExpectedOutput("0, 0, 0, 0")); } [Fact] public void Constants_Fields_02() { var source0 = @"public class A { public const nint C1 = -42; public const nuint C2 = 42; }"; var comp = CreateCompilation(source0, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); var ref0 = comp.EmitToImageReference(); var source1 = @"using System; class B { static void Main() { Console.WriteLine(A.C1); Console.WriteLine(A.C2); } }"; comp = CreateCompilation(source1, references: new[] { ref0 }, parseOptions: TestOptions.Regular9, options: TestOptions.ReleaseExe, targetFramework: TargetFramework.Net70); CompileAndVerify(comp, verify: Verification.FailsPEVerify, expectedOutput: IncludeExpectedOutput( @"-42 42")); } [Fact] public void Constants_ParameterDefaults() { var source0 = @"public class A { public static System.IntPtr F1(System.IntPtr i = -42) => i; public static nint F2(nint i = -42) => i; public static System.UIntPtr F3(System.UIntPtr u = 42) => u; public static nuint F4(nuint u = 42) => u; }"; var comp = CreateCompilation(source0, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); var ref0 = comp.EmitToImageReference(); var source1 = @"using System; class B { static void Main() { Console.WriteLine(A.F1()); Console.WriteLine(A.F2()); Console.WriteLine(A.F3()); Console.WriteLine(A.F4()); } }"; comp = CreateCompilation(source1, references: new[] { ref0 }, parseOptions: TestOptions.Regular9, options: TestOptions.ReleaseExe, targetFramework: TargetFramework.Net70); CompileAndVerify(comp, verify: Verification.FailsPEVerify, expectedOutput: IncludeExpectedOutput( @"-42 -42 42 42")); } [Fact] public void ConstantValue_Properties() { var source = @"using System; class Program { const IntPtr A = int.MinValue; const IntPtr B = 0; const IntPtr C = int.MaxValue; const UIntPtr D = 0; const UIntPtr E = uint.MaxValue; }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); verify((FieldSymbol)comp.GetMember("Program.A"), int.MinValue, signed: true, negative: true); verify((FieldSymbol)comp.GetMember("Program.B"), 0, signed: true, negative: false); verify((FieldSymbol)comp.GetMember("Program.C"), int.MaxValue, signed: true, negative: false); verify((FieldSymbol)comp.GetMember("Program.D"), 0U, signed: false, negative: false); verify((FieldSymbol)comp.GetMember("Program.E"), uint.MaxValue, signed: false, negative: false); static void verify(FieldSymbol field, object expectedValue, bool signed, bool negative) { var value = field.GetConstantValue(ConstantFieldsInProgress.Empty, earlyDecodingWellKnownAttributes: false); Assert.Equal(signed ? ConstantValueTypeDiscriminator.NInt : ConstantValueTypeDiscriminator.NUInt, value.Discriminator); Assert.Equal(expectedValue, value.Value); Assert.True(value.IsIntegral); Assert.True(value.IsNumeric); Assert.Equal(negative, value.IsNegativeNumeric); Assert.Equal(!signed, value.IsUnsigned); } } /// <summary> /// Native integers cannot be used as attribute values. /// </summary> [Fact] public void AttributeValue_01() { var source0 = @"using System; class A : System.Attribute { public A() { } public A(object value) { } public object Value; } [A((IntPtr)1)] [A(new IntPtr[0])] [A(Value = (IntPtr)3)] [A(Value = new[] { (IntPtr)4 })] class B { }"; var comp = CreateCompilation(source0, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics( // (8,4): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type // [A((IntPtr)1)] Diagnostic(ErrorCode.ERR_BadAttributeArgument, "(IntPtr)1").WithLocation(8, 4), // (9,4): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type // [A(new IntPtr[0])] Diagnostic(ErrorCode.ERR_BadAttributeArgument, "new IntPtr[0]").WithLocation(9, 4), // (10,12): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type // [A(Value = (IntPtr)3)] Diagnostic(ErrorCode.ERR_BadAttributeArgument, "(IntPtr)3").WithLocation(10, 12), // (11,12): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type // [A(Value = new[] { (IntPtr)4 })] Diagnostic(ErrorCode.ERR_BadAttributeArgument, "new[] { (IntPtr)4 }").WithLocation(11, 12)); } [Fact] public void AttributeValue_02() { var source0 = @"using System; class A : System.Attribute { public A() { } public A(IntPtr value) { } public IntPtr[] Value; } [A(1)] [A(Value = default)] class B { }"; var comp = CreateCompilation(source0, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics( // (8,2): error CS0181: Attribute constructor parameter 'value' has type 'nint', which is not a valid attribute parameter type // [A(1)] Diagnostic(ErrorCode.ERR_BadAttributeParamType, "A").WithArguments("value", "nint").WithLocation(8, 2), // (9,4): error CS0655: 'Value' is not a valid named attribute argument because it is not a valid attribute parameter type // [A(Value = default)] Diagnostic(ErrorCode.ERR_BadNamedAttributeArgumentType, "Value").WithArguments("Value").WithLocation(9, 4)); } [Fact] public void ParameterDefaultValue_01() { var source = @"using System; class A { static void F0(IntPtr x = default, UIntPtr y = default) { } static void F1(IntPtr x = (IntPtr)(-1), UIntPtr y = (UIntPtr)2) { } static void F2(IntPtr? x = null, UIntPtr? y = null) { } static void F3(IntPtr? x = (IntPtr)(-3), UIntPtr? y = (UIntPtr)4) { } }"; var comp = CreateCompilation(source); comp.VerifyDiagnostics( // (7,31): error CS1736: Default parameter value for 'x' must be a compile-time constant // static void F1(IntPtr x = (IntPtr)(-1), UIntPtr y = (UIntPtr)2) Diagnostic(ErrorCode.ERR_DefaultValueMustBeConstant, "(IntPtr)(-1)").WithArguments("x").WithLocation(7, 31), // (7,57): error CS1736: Default parameter value for 'y' must be a compile-time constant // static void F1(IntPtr x = (IntPtr)(-1), UIntPtr y = (UIntPtr)2) Diagnostic(ErrorCode.ERR_DefaultValueMustBeConstant, "(UIntPtr)2").WithArguments("y").WithLocation(7, 57), // (13,32): error CS1736: Default parameter value for 'x' must be a compile-time constant // static void F3(IntPtr? x = (IntPtr)(-3), UIntPtr? y = (UIntPtr)4) Diagnostic(ErrorCode.ERR_DefaultValueMustBeConstant, "(IntPtr)(-3)").WithArguments("x").WithLocation(13, 32), // (13,59): error CS1736: Default parameter value for 'y' must be a compile-time constant // static void F3(IntPtr? x = (IntPtr)(-3), UIntPtr? y = (UIntPtr)4) Diagnostic(ErrorCode.ERR_DefaultValueMustBeConstant, "(UIntPtr)4").WithArguments("y").WithLocation(13, 59)); } [Fact] public void ParameterDefaultValue_02() { var sourceA = @"using System; public class A { public static void F0(IntPtr x = default, UIntPtr y = default) { Report(x); Report(y); } public static void F1(IntPtr x = -1, UIntPtr y = 2) { Report(x); Report(y); } public static void F2(IntPtr? x = null, UIntPtr? y = null) { Report(x); Report(y); } public static void F3(IntPtr? x = -3, UIntPtr? y = 4) { Report(x); Report(y); } static void Report(object o) { System.Console.WriteLine(o ?? ""null""); } }"; var sourceB = @"class B { static void Main() { A.F0(); A.F1(); A.F2(); A.F3(); } }"; var expectedOutput = @"0 0 -1 2 null null -3 4"; var comp = CreateCompilation(new[] { sourceA, sourceB }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); CompileAndVerify(comp, expectedOutput: IncludeExpectedOutput(expectedOutput), verify: Verification.FailsPEVerify); comp = CreateCompilation(sourceA, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); var ref1 = comp.ToMetadataReference(); var ref2 = comp.EmitToImageReference(); comp = CreateCompilation(sourceB, references: new[] { ref1 }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); CompileAndVerify(comp, expectedOutput: IncludeExpectedOutput(expectedOutput), verify: Verification.FailsPEVerify); comp = CreateCompilation(sourceB, references: new[] { ref2 }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); CompileAndVerify(comp, expectedOutput: IncludeExpectedOutput(expectedOutput), verify: Verification.FailsPEVerify); comp = CreateCompilation(sourceB, references: new[] { ref1 }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular8, targetFramework: TargetFramework.Net70); CompileAndVerify(comp, expectedOutput: IncludeExpectedOutput(expectedOutput), verify: Verification.FailsPEVerify); comp = CreateCompilation(sourceB, references: new[] { ref2 }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular8, targetFramework: TargetFramework.Net70); CompileAndVerify(comp, expectedOutput: IncludeExpectedOutput(expectedOutput), verify: Verification.FailsPEVerify); } [Fact] public void SwitchStatement_01() { var source = @"using System; class Program { static IntPtr M(IntPtr ret) { switch (ret) { case 0: ret--; // 2 Report(""case 0: "", ret); goto case 9999; case 2: ret--; // 4 Report(""case 2: "", ret); goto case 255; case 6: // start here ret--; // 5 Report(""case 6: "", ret); goto case 2; case 9999: ret--; // 1 Report(""case 9999: "", ret); goto default; case 0xff: ret--; // 3 Report(""case 0xff: "", ret); goto case 0; default: ret--; Report(""default: "", ret); if (ret > 0) { goto case -1; } break; case -1: ret = 999; Report(""case -1: "", ret); break; } return(ret); } static void Report(string prefix, nint value) { Console.WriteLine(prefix + value); } static void Main() { Console.WriteLine(M(6)); } }"; var comp = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); var verifier = CompileAndVerify(comp, verify: Verification.FailsPEVerify, expectedOutput: IncludeExpectedOutput( @"case 6: 5 case 2: 4 case 0xff: 3 case 0: 2 case 9999: 1 default: 0 0")); verifier.VerifyIL("Program.M", @" { // Code size 201 (0xc9) .maxstack 3 .locals init (long V_0) IL_0000: ldarg.0 IL_0001: conv.i8 IL_0002: stloc.0 IL_0003: ldloc.0 IL_0004: ldc.i4.6 IL_0005: conv.i8 IL_0006: bgt.s IL_0031 IL_0008: ldloc.0 IL_0009: ldc.i4.m1 IL_000a: conv.i8 IL_000b: sub IL_000c: dup IL_000d: ldc.i4.3 IL_000e: conv.i8 IL_000f: ble.un.s IL_0014 IL_0011: pop IL_0012: br.s IL_002a IL_0014: conv.u4 IL_0015: switch ( IL_00b4, IL_0045, IL_009f, IL_0057) IL_002a: ldloc.0 IL_002b: ldc.i4.6 IL_002c: conv.i8 IL_002d: beq.s IL_0069 IL_002f: br.s IL_009f IL_0031: ldloc.0 IL_0032: ldc.i4 0xff IL_0037: conv.i8 IL_0038: beq.s IL_008d IL_003a: ldloc.0 IL_003b: ldc.i4 0x270f IL_0040: conv.i8 IL_0041: beq.s IL_007b IL_0043: br.s IL_009f IL_0045: ldarg.0 IL_0046: ldc.i4.1 IL_0047: sub IL_0048: starg.s V_0 IL_004a: ldstr ""case 0: "" IL_004f: ldarg.0 IL_0050: call ""void Program.Report(string, nint)"" IL_0055: br.s IL_007b IL_0057: ldarg.0 IL_0058: ldc.i4.1 IL_0059: sub IL_005a: starg.s V_0 IL_005c: ldstr ""case 2: "" IL_0061: ldarg.0 IL_0062: call ""void Program.Report(string, nint)"" IL_0067: br.s IL_008d IL_0069: ldarg.0 IL_006a: ldc.i4.1 IL_006b: sub IL_006c: starg.s V_0 IL_006e: ldstr ""case 6: "" IL_0073: ldarg.0 IL_0074: call ""void Program.Report(string, nint)"" IL_0079: br.s IL_0057 IL_007b: ldarg.0 IL_007c: ldc.i4.1 IL_007d: sub IL_007e: starg.s V_0 IL_0080: ldstr ""case 9999: "" IL_0085: ldarg.0 IL_0086: call ""void Program.Report(string, nint)"" IL_008b: br.s IL_009f IL_008d: ldarg.0 IL_008e: ldc.i4.1 IL_008f: sub IL_0090: starg.s V_0 IL_0092: ldstr ""case 0xff: "" IL_0097: ldarg.0 IL_0098: call ""void Program.Report(string, nint)"" IL_009d: br.s IL_0045 IL_009f: ldarg.0 IL_00a0: ldc.i4.1 IL_00a1: sub IL_00a2: starg.s V_0 IL_00a4: ldstr ""default: "" IL_00a9: ldarg.0 IL_00aa: call ""void Program.Report(string, nint)"" IL_00af: ldarg.0 IL_00b0: ldc.i4.0 IL_00b1: conv.i IL_00b2: ble.s IL_00c7 IL_00b4: ldc.i4 0x3e7 IL_00b9: conv.i IL_00ba: starg.s V_0 IL_00bc: ldstr ""case -1: "" IL_00c1: ldarg.0 IL_00c2: call ""void Program.Report(string, nint)"" IL_00c7: ldarg.0 IL_00c8: ret } ", ilFormat: ILFormat); } [Fact] public void SwitchStatement_02() { var source = @"using System; class Program { static UIntPtr M(UIntPtr ret) { switch (ret) { case 0: ret--; // 2 Report(""case 0: "", ret); goto case 9999; case 2: ret--; // 4 Report(""case 2: "", ret); goto case 255; case 6: // start here ret--; // 5 Report(""case 6: "", ret); goto case 2; case 9999: ret--; // 1 Report(""case 9999: "", ret); goto default; case 0xff: ret--; // 3 Report(""case 0xff: "", ret); goto case 0; default: ret--; Report(""default: "", ret); if (ret > 0) { goto case int.MaxValue; } break; case int.MaxValue: ret = 999; Report(""case int.MaxValue: "", ret); break; } return(ret); } static void Report(string prefix, nuint value) { Console.WriteLine(prefix + value); } static void Main() { Console.WriteLine(M(6)); } }"; var comp = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); var verifier = CompileAndVerify(comp, verify: Verification.FailsPEVerify, expectedOutput: IncludeExpectedOutput( @"case 6: 5 case 2: 4 case 0xff: 3 case 0: 2 case 9999: 1 default: 0 0")); verifier.VerifyIL("Program.M", @" { // Code size 184 (0xb8) .maxstack 2 .locals init (ulong V_0) IL_0000: ldarg.0 IL_0001: conv.u8 IL_0002: stloc.0 IL_0003: ldloc.0 IL_0004: ldc.i4.6 IL_0005: conv.i8 IL_0006: bgt.un.s IL_0017 IL_0008: ldloc.0 IL_0009: brfalse.s IL_0034 IL_000b: ldloc.0 IL_000c: ldc.i4.2 IL_000d: conv.i8 IL_000e: beq.s IL_0046 IL_0010: ldloc.0 IL_0011: ldc.i4.6 IL_0012: conv.i8 IL_0013: beq.s IL_0058 IL_0015: br.s IL_008e IL_0017: ldloc.0 IL_0018: ldc.i4 0xff IL_001d: conv.i8 IL_001e: beq.s IL_007c IL_0020: ldloc.0 IL_0021: ldc.i4 0x270f IL_0026: conv.i8 IL_0027: beq.s IL_006a IL_0029: ldloc.0 IL_002a: ldc.i4 0x7fffffff IL_002f: conv.i8 IL_0030: beq.s IL_00a3 IL_0032: br.s IL_008e IL_0034: ldarg.0 IL_0035: ldc.i4.1 IL_0036: sub IL_0037: starg.s V_0 IL_0039: ldstr ""case 0: "" IL_003e: ldarg.0 IL_003f: call ""void Program.Report(string, nuint)"" IL_0044: br.s IL_006a IL_0046: ldarg.0 IL_0047: ldc.i4.1 IL_0048: sub IL_0049: starg.s V_0 IL_004b: ldstr ""case 2: "" IL_0050: ldarg.0 IL_0051: call ""void Program.Report(string, nuint)"" IL_0056: br.s IL_007c IL_0058: ldarg.0 IL_0059: ldc.i4.1 IL_005a: sub IL_005b: starg.s V_0 IL_005d: ldstr ""case 6: "" IL_0062: ldarg.0 IL_0063: call ""void Program.Report(string, nuint)"" IL_0068: br.s IL_0046 IL_006a: ldarg.0 IL_006b: ldc.i4.1 IL_006c: sub IL_006d: starg.s V_0 IL_006f: ldstr ""case 9999: "" IL_0074: ldarg.0 IL_0075: call ""void Program.Report(string, nuint)"" IL_007a: br.s IL_008e IL_007c: ldarg.0 IL_007d: ldc.i4.1 IL_007e: sub IL_007f: starg.s V_0 IL_0081: ldstr ""case 0xff: "" IL_0086: ldarg.0 IL_0087: call ""void Program.Report(string, nuint)"" IL_008c: br.s IL_0034 IL_008e: ldarg.0 IL_008f: ldc.i4.1 IL_0090: sub IL_0091: starg.s V_0 IL_0093: ldstr ""default: "" IL_0098: ldarg.0 IL_0099: call ""void Program.Report(string, nuint)"" IL_009e: ldarg.0 IL_009f: ldc.i4.0 IL_00a0: conv.i IL_00a1: ble.un.s IL_00b6 IL_00a3: ldc.i4 0x3e7 IL_00a8: conv.i IL_00a9: starg.s V_0 IL_00ab: ldstr ""case int.MaxValue: "" IL_00b0: ldarg.0 IL_00b1: call ""void Program.Report(string, nuint)"" IL_00b6: ldarg.0 IL_00b7: ret } ", ilFormat: ILFormat); } [Fact] public void Conversions() { const string convNone = @"{ // Code size 2 (0x2) .maxstack 1 IL_0000: ldarg.0 IL_0001: ret }"; static string conv(string conversion) => $@"{{ // Code size 3 (0x3) .maxstack 1 IL_0000: ldarg.0 IL_0001: {conversion} IL_0002: ret }}"; static string convRUn(string conversion) => $@"{{ // Code size 4 (0x4) .maxstack 1 IL_0000: ldarg.0 IL_0001: conv.r.un IL_0002: {conversion} IL_0003: ret }}"; static string convFromNullableT(string conversion, string sourceType) => $@"{{ // Code size 9 (0x9) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly {sourceType} {sourceType}?.Value.get"" IL_0007: {conversion} IL_0008: ret }}"; static string convRUnFromNullableT(string conversion, string sourceType) => $@"{{ // Code size 10 (0xa) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly {sourceType} {sourceType}?.Value.get"" IL_0007: conv.r.un IL_0008: {conversion} IL_0009: ret }}"; static string convToNullableT(string conversion, string destType) => $@"{{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarg.0 IL_0001: {conversion} IL_0002: newobj ""{destType}?..ctor({destType})"" IL_0007: ret }}"; static string convRUnToNullableT(string conversion, string destType) => $@"{{ // Code size 9 (0x9) .maxstack 1 IL_0000: ldarg.0 IL_0001: conv.r.un IL_0002: {conversion} IL_0003: newobj ""{destType}?..ctor({destType})"" IL_0008: ret }}"; static string convFromToNullableT(string conversion, string sourceType, string destType) => $@"{{ // Code size 35 (0x23) .maxstack 1 .locals init ({sourceType}? V_0, {destType}? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool {sourceType}?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""{destType}?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly {sourceType} {sourceType}?.GetValueOrDefault()"" IL_001c: {conversion} IL_001d: newobj ""{destType}?..ctor({destType})"" IL_0022: ret }}"; static string convRUnFromToNullableT(string conversion, string sourceType, string destType) => $@"{{ // Code size 36 (0x24) .maxstack 1 .locals init ({sourceType}? V_0, {destType}? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool {sourceType}?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""{destType}?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly {sourceType} {sourceType}?.GetValueOrDefault()"" IL_001c: conv.r.un IL_001d: {conversion} IL_001e: newobj ""{destType}?..ctor({destType})"" IL_0023: ret }}"; static string convExplicitFromNullableT(string sourceType, string method) => $@"{{ // Code size 27 (0x1b) .maxstack 1 .locals init ({sourceType}? V_0) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool {sourceType}?.HasValue.get"" IL_0009: brtrue.s IL_000e IL_000b: ldc.i4.0 IL_000c: conv.u IL_000d: ret IL_000e: ldloca.s V_0 IL_0010: call ""readonly {sourceType} {sourceType}?.GetValueOrDefault()"" IL_0015: call ""{method}"" IL_001a: ret }}"; void conversions(string sourceType, string destType, ConversionKind[] expectedConversions, string expectedImplicitIL, string expectedExplicitIL, string expectedCheckedIL = null) { if (expectedExplicitIL is not null) { Assert.False(IsNoConversion(expectedConversions)); } convert( sourceType, destType, expectedImplicitIL, useExplicitCast: false, useChecked: false, expectedConversions: expectedConversions, expectedErrorCode: expectedImplicitIL is null ? expectedExplicitIL is null ? ErrorCode.ERR_NoImplicitConv : ErrorCode.ERR_NoImplicitConvCast : 0); // Explicit cast convert( sourceType, destType, expectedExplicitIL, useExplicitCast: true, useChecked: false, expectedConversions: null, expectedErrorCode: expectedExplicitIL is null ? ErrorCode.ERR_NoExplicitConv : 0); // Explicit cast and checked expectedCheckedIL ??= expectedExplicitIL; convert( sourceType, destType, expectedCheckedIL, useExplicitCast: true, useChecked: true, expectedConversions: null, expectedErrorCode: expectedCheckedIL is null ? ErrorCode.ERR_NoExplicitConv : 0); } // Test start: // type to nint conversions(sourceType: "object", destType: "nint", Unboxing, expectedImplicitIL: null, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: unbox.any ""nint"" IL_0006: ret }"); conversions(sourceType: "string", destType: "nint", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "void*", destType: "nint", ExplicitPointerToInteger, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.i.un")); conversions(sourceType: "delegate*<void>", destType: "nint", ExplicitPointerToInteger, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.i.un")); conversions(sourceType: "E", destType: "nint", ExplicitEnumeration, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i")); conversions(sourceType: "bool", destType: "nint", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "char", destType: "nint", ImplicitNumeric, expectedImplicitIL: conv("conv.u"), expectedExplicitIL: conv("conv.u")); conversions(sourceType: "sbyte", destType: "nint", ImplicitNumeric, expectedImplicitIL: conv("conv.i"), expectedExplicitIL: conv("conv.i")); conversions(sourceType: "byte", destType: "nint", ImplicitNumeric, expectedImplicitIL: conv("conv.u"), expectedExplicitIL: conv("conv.u")); conversions(sourceType: "short", destType: "nint", ImplicitNumeric, expectedImplicitIL: conv("conv.i"), expectedExplicitIL: conv("conv.i")); conversions(sourceType: "ushort", destType: "nint", ImplicitNumeric, expectedImplicitIL: conv("conv.u"), expectedExplicitIL: conv("conv.u")); conversions(sourceType: "int", destType: "nint", ImplicitNumeric, expectedImplicitIL: conv("conv.i"), expectedExplicitIL: conv("conv.i")); conversions(sourceType: "uint", destType: "nint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.i.un")); conversions(sourceType: "long", destType: "nint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.i")); conversions(sourceType: "ulong", destType: "nint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.i.un")); conversions(sourceType: "nint", destType: "nint", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); conversions(sourceType: "nuint", destType: "nint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.i.un")); conversions(sourceType: "float", destType: "nint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.i")); conversions(sourceType: "double", destType: "nint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.i")); conversions(sourceType: "decimal", destType: "nint", ExplicitNumeric, expectedImplicitIL: null, @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarg.0 IL_0001: call ""long decimal.op_Explicit(decimal)"" IL_0006: conv.i IL_0007: ret }", @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarg.0 IL_0001: call ""long decimal.op_Explicit(decimal)"" IL_0006: conv.ovf.i IL_0007: ret }"); conversions(sourceType: "System.IntPtr", destType: "nint", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); conversions(sourceType: "System.UIntPtr", destType: "nint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.i.un")); // nullable type to nint conversions(sourceType: "E?", destType: "nint", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "E")); conversions(sourceType: "bool?", destType: "nint", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "char?", destType: "nint", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "char")); conversions(sourceType: "sbyte?", destType: "nint", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "sbyte")); conversions(sourceType: "byte?", destType: "nint", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "byte")); conversions(sourceType: "short?", destType: "nint", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "short")); conversions(sourceType: "ushort?", destType: "nint", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "ushort")); conversions(sourceType: "int?", destType: "nint", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "int")); conversions(sourceType: "uint?", destType: "nint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "uint"), expectedCheckedIL: convFromNullableT("conv.ovf.i.un", "uint")); conversions(sourceType: "long?", destType: "nint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "long"), expectedCheckedIL: convFromNullableT("conv.ovf.i", "long")); conversions(sourceType: "ulong?", destType: "nint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "ulong"), expectedCheckedIL: convFromNullableT("conv.ovf.i.un", "ulong")); conversions(sourceType: "nint?", destType: "nint", ExplicitNullableIdentity, expectedImplicitIL: null, @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly nint nint?.Value.get"" IL_0007: ret }"); conversions(sourceType: "nuint?", destType: "nint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 8 (0x8) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly nuint nuint?.Value.get"" IL_0007: ret } ", expectedCheckedIL: convFromNullableT("conv.ovf.i.un", "nuint")); conversions(sourceType: "float?", destType: "nint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "float"), expectedCheckedIL: convFromNullableT("conv.ovf.i", "float")); conversions(sourceType: "double?", destType: "nint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "double"), expectedCheckedIL: convFromNullableT("conv.ovf.i", "double")); conversions(sourceType: "decimal?", destType: "nint", ExplicitNullableNumeric, expectedImplicitIL: null, @"{ // Code size 14 (0xe) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly decimal decimal?.Value.get"" IL_0007: call ""long decimal.op_Explicit(decimal)"" IL_000c: conv.i IL_000d: ret }", @"{ // Code size 14 (0xe) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly decimal decimal?.Value.get"" IL_0007: call ""long decimal.op_Explicit(decimal)"" IL_000c: conv.ovf.i IL_000d: ret }"); conversions(sourceType: "System.IntPtr?", destType: "nint", ExplicitNullableIdentity, expectedImplicitIL: null, @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly nint nint?.Value.get"" IL_0007: ret }"); conversions(sourceType: "System.UIntPtr?", destType: "nint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 8 (0x8) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly nuint nuint?.Value.get"" IL_0007: ret } ", expectedCheckedIL: convFromNullableT("conv.ovf.i.un", "nuint")); // type to nullable nint conversions(sourceType: "object", destType: "nint?", Unboxing, expectedImplicitIL: null, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: unbox.any ""nint?"" IL_0006: ret }"); conversions(sourceType: "string", destType: "nint?", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "void*", destType: "nint?", ExplicitNullablePointerToInteger, expectedImplicitIL: null, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret }", @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarg.0 IL_0001: conv.ovf.i.un IL_0002: newobj ""nint?..ctor(nint)"" IL_0007: ret }"); conversions(sourceType: "delegate*<void>", destType: "nint?", ExplicitNullablePointerToInteger, expectedImplicitIL: null, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret }", @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarg.0 IL_0001: conv.ovf.i.un IL_0002: newobj ""nint?..ctor(nint)"" IL_0007: ret }"); conversions(sourceType: "E", destType: "nint?", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nint")); conversions(sourceType: "bool", destType: "nint?", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "char", destType: "nint?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.u", "nint"), expectedExplicitIL: convToNullableT("conv.u", "nint")); conversions(sourceType: "sbyte", destType: "nint?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.i", "nint"), expectedExplicitIL: convToNullableT("conv.i", "nint")); conversions(sourceType: "byte", destType: "nint?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.u", "nint"), expectedExplicitIL: convToNullableT("conv.u", "nint")); conversions(sourceType: "short", destType: "nint?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.i", "nint"), expectedExplicitIL: convToNullableT("conv.i", "nint")); conversions(sourceType: "ushort", destType: "nint?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.u", "nint"), expectedExplicitIL: convToNullableT("conv.u", "nint")); conversions(sourceType: "int", destType: "nint?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.i", "nint"), expectedExplicitIL: convToNullableT("conv.i", "nint")); conversions(sourceType: "uint", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u", "nint"), expectedCheckedIL: convToNullableT("conv.ovf.i.un", "nint")); conversions(sourceType: "long", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nint"), expectedCheckedIL: convToNullableT("conv.ovf.i", "nint")); conversions(sourceType: "ulong", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nint"), expectedCheckedIL: convToNullableT("conv.ovf.i.un", "nint")); conversions(sourceType: "nint", destType: "nint?", ImplicitNullableIdentity, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret }", @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret }"); conversions(sourceType: "nuint", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret } ", expectedCheckedIL: convToNullableT("conv.ovf.i.un", "nint")); conversions(sourceType: "float", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nint"), expectedCheckedIL: convToNullableT("conv.ovf.i", "nint")); conversions(sourceType: "double", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nint"), expectedCheckedIL: convToNullableT("conv.ovf.i", "nint")); conversions(sourceType: "decimal", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, @"{ // Code size 13 (0xd) .maxstack 1 IL_0000: ldarg.0 IL_0001: call ""long decimal.op_Explicit(decimal)"" IL_0006: conv.i IL_0007: newobj ""nint?..ctor(nint)"" IL_000c: ret }", @"{ // Code size 13 (0xd) .maxstack 1 IL_0000: ldarg.0 IL_0001: call ""long decimal.op_Explicit(decimal)"" IL_0006: conv.ovf.i IL_0007: newobj ""nint?..ctor(nint)"" IL_000c: ret }"); conversions(sourceType: "System.IntPtr", destType: "nint?", ImplicitNullableIdentity, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret }", @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret }"); conversions(sourceType: "System.UIntPtr", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret } ", expectedCheckedIL: convToNullableT("conv.ovf.i.un", "nint")); // nullable type to nullable nint conversions(sourceType: "E?", destType: "nint?", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "E", "nint")); conversions(sourceType: "bool?", destType: "nint?", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "char?", destType: "nint?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.u", "char", "nint"), expectedExplicitIL: convFromToNullableT("conv.u", "char", "nint")); conversions(sourceType: "sbyte?", destType: "nint?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.i", "sbyte", "nint"), expectedExplicitIL: convFromToNullableT("conv.i", "sbyte", "nint")); conversions(sourceType: "byte?", destType: "nint?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.u", "byte", "nint"), expectedExplicitIL: convFromToNullableT("conv.u", "byte", "nint")); conversions(sourceType: "short?", destType: "nint?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.i", "short", "nint"), expectedExplicitIL: convFromToNullableT("conv.i", "short", "nint")); conversions(sourceType: "ushort?", destType: "nint?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.u", "ushort", "nint"), expectedExplicitIL: convFromToNullableT("conv.u", "ushort", "nint")); conversions(sourceType: "int?", destType: "nint?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.i", "int", "nint"), expectedExplicitIL: convFromToNullableT("conv.i", "int", "nint")); conversions(sourceType: "uint?", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "uint", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i.un", "uint", "nint")); conversions(sourceType: "long?", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "long", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i", "long", "nint")); conversions(sourceType: "ulong?", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "ulong", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i.un", "ulong", "nint")); conversions(sourceType: "nint?", destType: "nint?", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); conversions(sourceType: "nuint?", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 34 (0x22) .maxstack 1 .locals init (nuint? V_0, nint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nuint?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""nint?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly nuint nuint?.GetValueOrDefault()"" IL_001c: newobj ""nint?..ctor(nint)"" IL_0021: ret } ", expectedCheckedIL: convFromToNullableT("conv.ovf.i.un", "nuint", "nint")); conversions(sourceType: "float?", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "float", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i", "float", "nint")); conversions(sourceType: "double?", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "double", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i", "double", "nint")); conversions(sourceType: "decimal?", destType: "nint?", ExplicitNullableNumeric, null, @"{ // Code size 40 (0x28) .maxstack 1 .locals init (decimal? V_0, nint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool decimal?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""nint?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly decimal decimal?.GetValueOrDefault()"" IL_001c: call ""long decimal.op_Explicit(decimal)"" IL_0021: conv.i IL_0022: newobj ""nint?..ctor(nint)"" IL_0027: ret }", @"{ // Code size 40 (0x28) .maxstack 1 .locals init (decimal? V_0, nint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool decimal?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""nint?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly decimal decimal?.GetValueOrDefault()"" IL_001c: call ""long decimal.op_Explicit(decimal)"" IL_0021: conv.ovf.i IL_0022: newobj ""nint?..ctor(nint)"" IL_0027: ret }"); conversions(sourceType: "System.IntPtr?", destType: "nint?", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); conversions(sourceType: "System.UIntPtr?", destType: "nint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 34 (0x22) .maxstack 1 .locals init (nuint? V_0, nint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nuint?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""nint?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly nuint nuint?.GetValueOrDefault()"" IL_001c: newobj ""nint?..ctor(nint)"" IL_0021: ret } ", expectedCheckedIL: convFromToNullableT("conv.ovf.i.un", "nuint", "nint")); // nint to type conversions(sourceType: "nint", destType: "object", Boxing, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: box ""nint"" IL_0006: ret }", @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: box ""nint"" IL_0006: ret }"); conversions(sourceType: "nint", destType: "string", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "nint", destType: "void*", ExplicitIntegerToPointer, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "nint", destType: "delegate*<void>", ExplicitIntegerToPointer, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "nint", destType: "E", ExplicitEnumeration, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i4"), expectedCheckedIL: conv("conv.ovf.i4")); conversions(sourceType: "nint", destType: "bool", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "nint", destType: "char", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u2"), expectedCheckedIL: conv("conv.ovf.u2")); conversions(sourceType: "nint", destType: "sbyte", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i1"), expectedCheckedIL: conv("conv.ovf.i1")); conversions(sourceType: "nint", destType: "byte", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u1"), expectedCheckedIL: conv("conv.ovf.u1")); conversions(sourceType: "nint", destType: "short", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i2"), expectedCheckedIL: conv("conv.ovf.i2")); conversions(sourceType: "nint", destType: "ushort", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u2"), expectedCheckedIL: conv("conv.ovf.u2")); conversions(sourceType: "nint", destType: "int", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i4"), expectedCheckedIL: conv("conv.ovf.i4")); conversions(sourceType: "nint", destType: "uint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u4"), expectedCheckedIL: conv("conv.ovf.u4")); conversions(sourceType: "nint", destType: "long", ImplicitNumeric, expectedImplicitIL: conv("conv.i8"), expectedExplicitIL: conv("conv.i8")); conversions(sourceType: "nint", destType: "ulong", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i8"), expectedCheckedIL: conv("conv.ovf.u8")); conversions(sourceType: "nint", destType: "float", ImplicitNumeric, expectedImplicitIL: conv("conv.r4"), expectedExplicitIL: conv("conv.r4")); conversions(sourceType: "nint", destType: "double", ImplicitNumeric, expectedImplicitIL: conv("conv.r8"), expectedExplicitIL: conv("conv.r8")); conversions(sourceType: "nint", destType: "decimal", ImplicitNumeric, @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarg.0 IL_0001: conv.i8 IL_0002: call ""decimal decimal.op_Implicit(long)"" IL_0007: ret }", @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarg.0 IL_0001: conv.i8 IL_0002: call ""decimal decimal.op_Implicit(long)"" IL_0007: ret }"); conversions(sourceType: "nint", destType: "System.IntPtr", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); conversions(sourceType: "nint", destType: "System.UIntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.u")); // nint to nullable type conversions(sourceType: "nint", destType: "E?", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i4", "E"), expectedCheckedIL: convToNullableT("conv.ovf.i4", "E")); conversions(sourceType: "nint", destType: "bool?", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "nint", destType: "char?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u2", "char"), expectedCheckedIL: convToNullableT("conv.ovf.u2", "char")); conversions(sourceType: "nint", destType: "sbyte?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i1", "sbyte"), expectedCheckedIL: convToNullableT("conv.ovf.i1", "sbyte")); conversions(sourceType: "nint", destType: "byte?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u1", "byte"), expectedCheckedIL: convToNullableT("conv.ovf.u1", "byte")); conversions(sourceType: "nint", destType: "short?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i2", "short"), expectedCheckedIL: convToNullableT("conv.ovf.i2", "short")); conversions(sourceType: "nint", destType: "ushort?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u2", "ushort"), expectedCheckedIL: convToNullableT("conv.ovf.u2", "ushort")); conversions(sourceType: "nint", destType: "int?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i4", "int"), expectedCheckedIL: convToNullableT("conv.ovf.i4", "int")); conversions(sourceType: "nint", destType: "uint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u4", "uint"), expectedCheckedIL: convToNullableT("conv.ovf.u4", "uint")); conversions(sourceType: "nint", destType: "long?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.i8", "long"), expectedExplicitIL: convToNullableT("conv.i8", "long")); conversions(sourceType: "nint", destType: "ulong?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i8", "ulong"), expectedCheckedIL: convToNullableT("conv.ovf.u8", "ulong")); conversions(sourceType: "nint", destType: "float?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.r4", "float"), expectedExplicitIL: convToNullableT("conv.r4", "float"), null); conversions(sourceType: "nint", destType: "double?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.r8", "double"), expectedExplicitIL: convToNullableT("conv.r8", "double"), null); conversions(sourceType: "nint", destType: "decimal?", ImplicitNullableNumeric, @"{ // Code size 13 (0xd) .maxstack 1 IL_0000: ldarg.0 IL_0001: conv.i8 IL_0002: call ""decimal decimal.op_Implicit(long)"" IL_0007: newobj ""decimal?..ctor(decimal)"" IL_000c: ret }", @"{ // Code size 13 (0xd) .maxstack 1 IL_0000: ldarg.0 IL_0001: conv.i8 IL_0002: call ""decimal decimal.op_Implicit(long)"" IL_0007: newobj ""decimal?..ctor(decimal)"" IL_000c: ret }"); conversions(sourceType: "nint", destType: "System.IntPtr?", ImplicitNullableIdentity, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret }", @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret }"); conversions(sourceType: "nint", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nuint?..ctor(nuint)"" IL_0006: ret } ", expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); // nullable nint to type conversions(sourceType: "nint?", destType: "object", Boxing, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: box ""nint?"" IL_0006: ret }", @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: box ""nint?"" IL_0006: ret }"); conversions(sourceType: "nint?", destType: "string", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "nint?", destType: "void*", ExplicitUserDefined, expectedImplicitIL: null, expectedExplicitIL: convExplicitFromNullableT("nint", "void* nint.op_Explicit(nint)")); conversions(sourceType: "nint?", destType: "delegate*<void>", ExplicitUserDefined, expectedImplicitIL: null, expectedExplicitIL: convExplicitFromNullableT("nint", "void* nint.op_Explicit(nint)")); conversions(sourceType: "nint?", destType: "E", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i4", "nint"), expectedCheckedIL: convFromNullableT("conv.ovf.i4", "nint")); conversions(sourceType: "nint?", destType: "bool", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "nint?", destType: "char", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u2", "nint"), expectedCheckedIL: convFromNullableT("conv.ovf.u2", "nint")); conversions(sourceType: "nint?", destType: "sbyte", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i1", "nint"), expectedCheckedIL: convFromNullableT("conv.ovf.i1", "nint")); conversions(sourceType: "nint?", destType: "byte", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u1", "nint"), expectedCheckedIL: convFromNullableT("conv.ovf.u1", "nint")); conversions(sourceType: "nint?", destType: "short", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i2", "nint"), expectedCheckedIL: convFromNullableT("conv.ovf.i2", "nint")); conversions(sourceType: "nint?", destType: "ushort", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u2", "nint"), expectedCheckedIL: convFromNullableT("conv.ovf.u2", "nint")); conversions(sourceType: "nint?", destType: "int", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i4", "nint"), expectedCheckedIL: convFromNullableT("conv.ovf.i4", "nint")); conversions(sourceType: "nint?", destType: "uint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u4", "nint"), expectedCheckedIL: convFromNullableT("conv.ovf.u4", "nint")); conversions(sourceType: "nint?", destType: "long", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i8", "nint")); conversions(sourceType: "nint?", destType: "ulong", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i8", "nint"), expectedCheckedIL: convFromNullableT("conv.ovf.u8", "nint")); conversions(sourceType: "nint?", destType: "float", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.r4", "nint")); conversions(sourceType: "nint?", destType: "double", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.r8", "nint")); conversions(sourceType: "nint?", destType: "decimal", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, @"{ // Code size 14 (0xe) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly nint nint?.Value.get"" IL_0007: conv.i8 IL_0008: call ""decimal decimal.op_Implicit(long)"" IL_000d: ret }"); conversions(sourceType: "nint?", destType: "System.IntPtr", ExplicitNullableIdentity, expectedImplicitIL: null, @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly nint nint?.Value.get"" IL_0007: ret }"); conversions(sourceType: "nint?", destType: "System.UIntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 8 (0x8) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly nint nint?.Value.get"" IL_0007: ret } ", expectedCheckedIL: convFromNullableT("conv.ovf.u", "nint")); // nullable nint to nullable type conversions(sourceType: "nint?", destType: "E?", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i4", "nint", "E"), expectedCheckedIL: convFromToNullableT("conv.ovf.i4", "nint", "E")); conversions(sourceType: "nint?", destType: "bool?", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "nint?", destType: "char?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u2", "nint", "char"), expectedCheckedIL: convFromToNullableT("conv.ovf.u2", "nint", "char")); conversions(sourceType: "nint?", destType: "sbyte?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i1", "nint", "sbyte"), expectedCheckedIL: convFromToNullableT("conv.ovf.i1", "nint", "sbyte")); conversions(sourceType: "nint?", destType: "byte?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u1", "nint", "byte"), expectedCheckedIL: convFromToNullableT("conv.ovf.u1", "nint", "byte")); conversions(sourceType: "nint?", destType: "short?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i2", "nint", "short"), expectedCheckedIL: convFromToNullableT("conv.ovf.i2", "nint", "short")); conversions(sourceType: "nint?", destType: "ushort?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u2", "nint", "ushort"), expectedCheckedIL: convFromToNullableT("conv.ovf.u2", "nint", "ushort")); conversions(sourceType: "nint?", destType: "int?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i4", "nint", "int"), expectedCheckedIL: convFromToNullableT("conv.ovf.i4", "nint", "int")); conversions(sourceType: "nint?", destType: "uint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u4", "nint", "uint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u4", "nint", "uint")); conversions(sourceType: "nint?", destType: "long?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.i8", "nint", "long"), expectedExplicitIL: convFromToNullableT("conv.i8", "nint", "long")); conversions(sourceType: "nint?", destType: "ulong?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i8", "nint", "ulong"), expectedCheckedIL: convFromToNullableT("conv.ovf.u8", "nint", "ulong")); conversions(sourceType: "nint?", destType: "float?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.r4", "nint", "float"), expectedExplicitIL: convFromToNullableT("conv.r4", "nint", "float"), null); conversions(sourceType: "nint?", destType: "double?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.r8", "nint", "double"), expectedExplicitIL: convFromToNullableT("conv.r8", "nint", "double"), null); conversions(sourceType: "nint?", destType: "decimal?", ImplicitNullableNumeric, @"{ // Code size 40 (0x28) .maxstack 1 .locals init (nint? V_0, decimal? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nint?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""decimal?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly nint nint?.GetValueOrDefault()"" IL_001c: conv.i8 IL_001d: call ""decimal decimal.op_Implicit(long)"" IL_0022: newobj ""decimal?..ctor(decimal)"" IL_0027: ret }", @"{ // Code size 40 (0x28) .maxstack 1 .locals init (nint? V_0, decimal? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nint?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""decimal?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly nint nint?.GetValueOrDefault()"" IL_001c: conv.i8 IL_001d: call ""decimal decimal.op_Implicit(long)"" IL_0022: newobj ""decimal?..ctor(decimal)"" IL_0027: ret }"); conversions(sourceType: "nint?", destType: "System.IntPtr?", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); conversions(sourceType: "nint?", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 34 (0x22) .maxstack 1 .locals init (nint? V_0, nuint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nint?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""nuint?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly nint nint?.GetValueOrDefault()"" IL_001c: newobj ""nuint?..ctor(nuint)"" IL_0021: ret } ", expectedCheckedIL: convFromToNullableT("conv.ovf.u", "nint", "nuint")); // type to nuint conversions(sourceType: "object", destType: "nuint", Unboxing, expectedImplicitIL: null, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: unbox.any ""nuint"" IL_0006: ret }"); conversions(sourceType: "string", destType: "nuint", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "void*", destType: "nuint", ExplicitPointerToInteger, expectedImplicitIL: null, expectedExplicitIL: convNone); conversions(sourceType: "delegate*<void>", destType: "nuint", ExplicitPointerToInteger, expectedImplicitIL: null, expectedExplicitIL: convNone); conversions(sourceType: "E", destType: "nuint", ExplicitEnumeration, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "bool", destType: "nuint", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "char", destType: "nuint", ImplicitNumeric, expectedImplicitIL: conv("conv.u"), expectedExplicitIL: conv("conv.u")); conversions(sourceType: "sbyte", destType: "nuint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "byte", destType: "nuint", ImplicitNumeric, expectedImplicitIL: conv("conv.u"), expectedExplicitIL: conv("conv.u")); conversions(sourceType: "short", destType: "nuint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "ushort", destType: "nuint", ImplicitNumeric, expectedImplicitIL: conv("conv.u"), expectedExplicitIL: conv("conv.u")); conversions(sourceType: "int", destType: "nuint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "uint", destType: "nuint", ImplicitNumeric, expectedImplicitIL: conv("conv.u"), expectedExplicitIL: conv("conv.u")); conversions(sourceType: "long", destType: "nuint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "ulong", destType: "nuint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.u.un")); conversions(sourceType: "nint", destType: "nuint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "nuint", destType: "nuint", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); conversions(sourceType: "float", destType: "nuint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "double", destType: "nuint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "decimal", destType: "nuint", ExplicitNumeric, expectedImplicitIL: null, @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarg.0 IL_0001: call ""ulong decimal.op_Explicit(decimal)"" IL_0006: conv.u IL_0007: ret }", @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarg.0 IL_0001: call ""ulong decimal.op_Explicit(decimal)"" IL_0006: conv.ovf.u.un IL_0007: ret }"); conversions(sourceType: "System.IntPtr", destType: "nuint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "System.UIntPtr", destType: "nuint", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); // nullable type to nuint conversions(sourceType: "E?", destType: "nuint", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "E"), expectedCheckedIL: convFromNullableT("conv.ovf.u", "E")); conversions(sourceType: "bool?", destType: "nuint", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "char?", destType: "nuint", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "char")); conversions(sourceType: "sbyte?", destType: "nuint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "sbyte"), expectedCheckedIL: convFromNullableT("conv.ovf.u", "sbyte")); conversions(sourceType: "byte?", destType: "nuint", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "byte")); conversions(sourceType: "short?", destType: "nuint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "short"), expectedCheckedIL: convFromNullableT("conv.ovf.u", "short")); conversions(sourceType: "ushort?", destType: "nuint", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "ushort")); conversions(sourceType: "int?", destType: "nuint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "int"), expectedCheckedIL: convFromNullableT("conv.ovf.u", "int")); conversions(sourceType: "uint?", destType: "nuint", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "uint")); conversions(sourceType: "long?", destType: "nuint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "long"), expectedCheckedIL: convFromNullableT("conv.ovf.u", "long")); conversions(sourceType: "ulong?", destType: "nuint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "ulong"), expectedCheckedIL: convFromNullableT("conv.ovf.u.un", "ulong")); conversions(sourceType: "nint?", destType: "nuint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 8 (0x8) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly nint nint?.Value.get"" IL_0007: ret } ", expectedCheckedIL: convFromNullableT("conv.ovf.u", "nint")); conversions(sourceType: "nuint?", destType: "nuint", ExplicitNullableIdentity, expectedImplicitIL: null, @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly nuint nuint?.Value.get"" IL_0007: ret }"); conversions(sourceType: "float?", destType: "nuint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "float"), expectedCheckedIL: convFromNullableT("conv.ovf.u", "float")); conversions(sourceType: "double?", destType: "nuint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "double"), expectedCheckedIL: convFromNullableT("conv.ovf.u", "double")); conversions(sourceType: "decimal?", destType: "nuint", ExplicitNullableNumeric, expectedImplicitIL: null, @"{ // Code size 14 (0xe) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly decimal decimal?.Value.get"" IL_0007: call ""ulong decimal.op_Explicit(decimal)"" IL_000c: conv.u IL_000d: ret }", @"{ // Code size 14 (0xe) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly decimal decimal?.Value.get"" IL_0007: call ""ulong decimal.op_Explicit(decimal)"" IL_000c: conv.ovf.u.un IL_000d: ret }"); conversions(sourceType: "System.IntPtr?", destType: "nuint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly nint nint?.Value.get"" IL_0007: ret }", expectedCheckedIL: convFromNullableT("conv.ovf.u", "nint")); conversions(sourceType: "System.UIntPtr?", destType: "nuint", ExplicitNullableIdentity, expectedImplicitIL: null, @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly nuint nuint?.Value.get"" IL_0007: ret }"); // type to nullable nuint conversions(sourceType: "object", destType: "nuint?", Unboxing, expectedImplicitIL: null, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: unbox.any ""nuint?"" IL_0006: ret }"); conversions(sourceType: "string", destType: "nuint?", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "void*", destType: "nuint?", ExplicitNullablePointerToInteger, expectedImplicitIL: null, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nuint?..ctor(nuint)"" IL_0006: ret }"); conversions(sourceType: "delegate*<void>", destType: "nuint?", ExplicitNullablePointerToInteger, expectedImplicitIL: null, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nuint?..ctor(nuint)"" IL_0006: ret }"); conversions(sourceType: "E", destType: "nuint?", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); conversions(sourceType: "bool", destType: "nuint?", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "char", destType: "nuint?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.u", "nuint"), expectedExplicitIL: convToNullableT("conv.u", "nuint")); conversions(sourceType: "sbyte", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); conversions(sourceType: "byte", destType: "nuint?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.u", "nuint"), expectedExplicitIL: convToNullableT("conv.u", "nuint")); conversions(sourceType: "short", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); conversions(sourceType: "ushort", destType: "nuint?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.u", "nuint"), expectedExplicitIL: convToNullableT("conv.u", "nuint")); conversions(sourceType: "int", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); conversions(sourceType: "uint", destType: "nuint?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.u", "nuint"), expectedExplicitIL: convToNullableT("conv.u", "nuint")); conversions(sourceType: "long", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); conversions(sourceType: "ulong", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u.un", "nuint")); conversions(sourceType: "nint", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nuint?..ctor(nuint)"" IL_0006: ret } ", expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); conversions(sourceType: "nuint", destType: "nuint?", ImplicitNullableIdentity, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nuint?..ctor(nuint)"" IL_0006: ret }", @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nuint?..ctor(nuint)"" IL_0006: ret }"); conversions(sourceType: "float", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); conversions(sourceType: "double", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); conversions(sourceType: "decimal", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, @"{ // Code size 13 (0xd) .maxstack 1 IL_0000: ldarg.0 IL_0001: call ""ulong decimal.op_Explicit(decimal)"" IL_0006: conv.u IL_0007: newobj ""nuint?..ctor(nuint)"" IL_000c: ret }", @"{ // Code size 13 (0xd) .maxstack 1 IL_0000: ldarg.0 IL_0001: call ""ulong decimal.op_Explicit(decimal)"" IL_0006: conv.ovf.u.un IL_0007: newobj ""nuint?..ctor(nuint)"" IL_000c: ret }"); conversions(sourceType: "System.IntPtr", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nuint?..ctor(nuint)"" IL_0006: ret } ", expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); conversions(sourceType: "System.UIntPtr", destType: "nuint?", ImplicitNullableIdentity, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nuint?..ctor(nuint)"" IL_0006: ret }", @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nuint?..ctor(nuint)"" IL_0006: ret }"); // nullable type to nullable nuint conversions(sourceType: "E?", destType: "nuint?", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "E", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "E", "nuint")); conversions(sourceType: "bool?", destType: "nuint?", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "char?", destType: "nuint?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.u", "char", "nuint"), expectedExplicitIL: convFromToNullableT("conv.u", "char", "nuint")); conversions(sourceType: "sbyte?", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "sbyte", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "sbyte", "nuint")); conversions(sourceType: "byte?", destType: "nuint?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.u", "byte", "nuint"), expectedExplicitIL: convFromToNullableT("conv.u", "byte", "nuint")); conversions(sourceType: "short?", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "short", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "short", "nuint")); conversions(sourceType: "ushort?", destType: "nuint?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.u", "ushort", "nuint"), expectedExplicitIL: convFromToNullableT("conv.u", "ushort", "nuint")); conversions(sourceType: "int?", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "int", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "int", "nuint")); conversions(sourceType: "uint?", destType: "nuint?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.u", "uint", "nuint"), expectedExplicitIL: convFromToNullableT("conv.u", "uint", "nuint")); conversions(sourceType: "long?", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "long", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "long", "nuint")); conversions(sourceType: "ulong?", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "ulong", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u.un", "ulong", "nuint")); conversions(sourceType: "nint?", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 34 (0x22) .maxstack 1 .locals init (nint? V_0, nuint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nint?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""nuint?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly nint nint?.GetValueOrDefault()"" IL_001c: newobj ""nuint?..ctor(nuint)"" IL_0021: ret } ", expectedCheckedIL: convFromToNullableT("conv.ovf.u", "nint", "nuint")); conversions(sourceType: "nuint?", destType: "nuint?", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); conversions(sourceType: "float?", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "float", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "float", "nuint")); conversions(sourceType: "double?", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "double", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "double", "nuint")); conversions(sourceType: "decimal?", destType: "nuint?", ExplicitNullableNumeric, null, @"{ // Code size 40 (0x28) .maxstack 1 .locals init (decimal? V_0, nuint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool decimal?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""nuint?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly decimal decimal?.GetValueOrDefault()"" IL_001c: call ""ulong decimal.op_Explicit(decimal)"" IL_0021: conv.u IL_0022: newobj ""nuint?..ctor(nuint)"" IL_0027: ret }", @"{ // Code size 40 (0x28) .maxstack 1 .locals init (decimal? V_0, nuint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool decimal?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""nuint?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly decimal decimal?.GetValueOrDefault()"" IL_001c: call ""ulong decimal.op_Explicit(decimal)"" IL_0021: conv.ovf.u.un IL_0022: newobj ""nuint?..ctor(nuint)"" IL_0027: ret }"); conversions(sourceType: "System.IntPtr?", destType: "nuint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 34 (0x22) .maxstack 1 .locals init (nint? V_0, nuint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nint?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""nuint?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly nint nint?.GetValueOrDefault()"" IL_001c: newobj ""nuint?..ctor(nuint)"" IL_0021: ret } ", expectedCheckedIL: convFromToNullableT("conv.ovf.u", "nint", "nuint")); conversions(sourceType: "System.UIntPtr?", destType: "nuint?", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); // nuint to type conversions(sourceType: "nuint", destType: "object", Boxing, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: box ""nuint"" IL_0006: ret }", @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: box ""nuint"" IL_0006: ret }"); conversions(sourceType: "nuint", destType: "string", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "nuint", destType: "void*", ExplicitIntegerToPointer, expectedImplicitIL: null, expectedExplicitIL: convNone); conversions(sourceType: "nuint", destType: "delegate*<void>", ExplicitIntegerToPointer, expectedImplicitIL: null, expectedExplicitIL: convNone); conversions(sourceType: "nuint", destType: "E", ExplicitEnumeration, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i4"), expectedCheckedIL: conv("conv.ovf.i4.un")); conversions(sourceType: "nuint", destType: "bool", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "nuint", destType: "char", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u2"), expectedCheckedIL: conv("conv.ovf.u2.un")); conversions(sourceType: "nuint", destType: "sbyte", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i1"), expectedCheckedIL: conv("conv.ovf.i1.un")); conversions(sourceType: "nuint", destType: "byte", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u1"), expectedCheckedIL: conv("conv.ovf.u1.un")); conversions(sourceType: "nuint", destType: "short", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i2"), expectedCheckedIL: conv("conv.ovf.i2.un")); conversions(sourceType: "nuint", destType: "ushort", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u2"), expectedCheckedIL: conv("conv.ovf.u2.un")); conversions(sourceType: "nuint", destType: "int", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i4"), expectedCheckedIL: conv("conv.ovf.i4.un")); conversions(sourceType: "nuint", destType: "uint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u4"), expectedCheckedIL: conv("conv.ovf.u4.un")); conversions(sourceType: "nuint", destType: "long", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u8"), expectedCheckedIL: conv("conv.ovf.i8.un")); conversions(sourceType: "nuint", destType: "ulong", ImplicitNumeric, expectedImplicitIL: conv("conv.u8"), expectedExplicitIL: conv("conv.u8")); conversions(sourceType: "nuint", destType: "float", ImplicitNumeric, expectedImplicitIL: convRUn("conv.r4"), expectedExplicitIL: convRUn("conv.r4")); conversions(sourceType: "nuint", destType: "double", ImplicitNumeric, expectedImplicitIL: convRUn("conv.r8"), expectedExplicitIL: convRUn("conv.r8")); conversions(sourceType: "nuint", destType: "decimal", ImplicitNumeric, @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarg.0 IL_0001: conv.u8 IL_0002: call ""decimal decimal.op_Implicit(ulong)"" IL_0007: ret }", @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarg.0 IL_0001: conv.u8 IL_0002: call ""decimal decimal.op_Implicit(ulong)"" IL_0007: ret }"); conversions(sourceType: "nuint", destType: "System.IntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.i.un")); conversions(sourceType: "nuint", destType: "System.UIntPtr", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); // nuint to nullable type conversions(sourceType: "nuint", destType: "E?", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i4", "E"), expectedCheckedIL: convToNullableT("conv.ovf.i4.un", "E")); conversions(sourceType: "nuint", destType: "bool?", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "nuint", destType: "char?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u2", "char"), expectedCheckedIL: convToNullableT("conv.ovf.u2.un", "char")); conversions(sourceType: "nuint", destType: "sbyte?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i1", "sbyte"), expectedCheckedIL: convToNullableT("conv.ovf.i1.un", "sbyte")); conversions(sourceType: "nuint", destType: "byte?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u1", "byte"), expectedCheckedIL: convToNullableT("conv.ovf.u1.un", "byte")); conversions(sourceType: "nuint", destType: "short?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i2", "short"), expectedCheckedIL: convToNullableT("conv.ovf.i2.un", "short")); conversions(sourceType: "nuint", destType: "ushort?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u2", "ushort"), expectedCheckedIL: convToNullableT("conv.ovf.u2.un", "ushort")); conversions(sourceType: "nuint", destType: "int?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i4", "int"), expectedCheckedIL: convToNullableT("conv.ovf.i4.un", "int")); conversions(sourceType: "nuint", destType: "uint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u4", "uint"), expectedCheckedIL: convToNullableT("conv.ovf.u4.un", "uint")); conversions(sourceType: "nuint", destType: "long?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u8", "long"), expectedCheckedIL: convToNullableT("conv.ovf.i8.un", "long")); conversions(sourceType: "nuint", destType: "ulong?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.u8", "ulong"), expectedExplicitIL: convToNullableT("conv.u8", "ulong")); conversions(sourceType: "nuint", destType: "float?", ImplicitNullableNumeric, expectedImplicitIL: convRUnToNullableT("conv.r4", "float"), expectedExplicitIL: convRUnToNullableT("conv.r4", "float"), null); conversions(sourceType: "nuint", destType: "double?", ImplicitNullableNumeric, expectedImplicitIL: convRUnToNullableT("conv.r8", "double"), expectedExplicitIL: convRUnToNullableT("conv.r8", "double"), null); conversions(sourceType: "nuint", destType: "decimal?", ImplicitNullableNumeric, @"{ // Code size 13 (0xd) .maxstack 1 IL_0000: ldarg.0 IL_0001: conv.u8 IL_0002: call ""decimal decimal.op_Implicit(ulong)"" IL_0007: newobj ""decimal?..ctor(decimal)"" IL_000c: ret }", @"{ // Code size 13 (0xd) .maxstack 1 IL_0000: ldarg.0 IL_0001: conv.u8 IL_0002: call ""decimal decimal.op_Implicit(ulong)"" IL_0007: newobj ""decimal?..ctor(decimal)"" IL_000c: ret }"); conversions(sourceType: "nuint", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret } ", expectedCheckedIL: convToNullableT("conv.ovf.i.un", "nint")); conversions(sourceType: "nuint", destType: "System.UIntPtr?", ImplicitNullableIdentity, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nuint?..ctor(nuint)"" IL_0006: ret }", @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nuint?..ctor(nuint)"" IL_0006: ret }"); // nullable nuint to type conversions(sourceType: "nuint?", destType: "object", Boxing, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: box ""nuint?"" IL_0006: ret }", @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: box ""nuint?"" IL_0006: ret }"); conversions(sourceType: "nuint?", destType: "string", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "nuint?", destType: "void*", ExplicitUserDefined, expectedImplicitIL: null, expectedExplicitIL: convExplicitFromNullableT("nuint", "void* nuint.op_Explicit(nuint)")); conversions(sourceType: "nuint?", destType: "delegate*<void>", ExplicitUserDefined, expectedImplicitIL: null, expectedExplicitIL: convExplicitFromNullableT("nuint", "void* nuint.op_Explicit(nuint)")); conversions(sourceType: "nuint?", destType: "E", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i4", "nuint"), expectedCheckedIL: convFromNullableT("conv.ovf.i4.un", "nuint")); conversions(sourceType: "nuint?", destType: "bool", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "nuint?", destType: "char", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u2", "nuint"), expectedCheckedIL: convFromNullableT("conv.ovf.u2.un", "nuint")); conversions(sourceType: "nuint?", destType: "sbyte", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i1", "nuint"), expectedCheckedIL: convFromNullableT("conv.ovf.i1.un", "nuint")); conversions(sourceType: "nuint?", destType: "byte", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u1", "nuint"), expectedCheckedIL: convFromNullableT("conv.ovf.u1.un", "nuint")); conversions(sourceType: "nuint?", destType: "short", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i2", "nuint"), expectedCheckedIL: convFromNullableT("conv.ovf.i2.un", "nuint")); conversions(sourceType: "nuint?", destType: "ushort", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u2", "nuint"), expectedCheckedIL: convFromNullableT("conv.ovf.u2.un", "nuint")); conversions(sourceType: "nuint?", destType: "int", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i4", "nuint"), expectedCheckedIL: convFromNullableT("conv.ovf.i4.un", "nuint")); conversions(sourceType: "nuint?", destType: "uint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u4", "nuint"), expectedCheckedIL: convFromNullableT("conv.ovf.u4.un", "nuint")); conversions(sourceType: "nuint?", destType: "long", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u8", "nuint"), expectedCheckedIL: convFromNullableT("conv.ovf.i8.un", "nuint")); conversions(sourceType: "nuint?", destType: "ulong", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u8", "nuint")); conversions(sourceType: "nuint?", destType: "float", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convRUnFromNullableT("conv.r4", "nuint")); conversions(sourceType: "nuint?", destType: "double", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convRUnFromNullableT("conv.r8", "nuint")); conversions(sourceType: "nuint?", destType: "decimal", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, @"{ // Code size 14 (0xe) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly nuint nuint?.Value.get"" IL_0007: conv.u8 IL_0008: call ""decimal decimal.op_Implicit(ulong)"" IL_000d: ret }"); conversions(sourceType: "nuint?", destType: "System.IntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 8 (0x8) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly nuint nuint?.Value.get"" IL_0007: ret } ", expectedCheckedIL: convFromNullableT("conv.ovf.i.un", "nuint")); conversions(sourceType: "nuint?", destType: "System.UIntPtr", ExplicitNullableIdentity, expectedImplicitIL: null, @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly nuint nuint?.Value.get"" IL_0007: ret }"); // nullable nuint to nullable type conversions(sourceType: "nuint?", destType: "E?", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i4", "nuint", "E"), expectedCheckedIL: convFromToNullableT("conv.ovf.i4.un", "nuint", "E")); conversions(sourceType: "nuint?", destType: "bool?", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "nuint?", destType: "char?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u2", "nuint", "char"), expectedCheckedIL: convFromToNullableT("conv.ovf.u2.un", "nuint", "char")); conversions(sourceType: "nuint?", destType: "sbyte?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i1", "nuint", "sbyte"), expectedCheckedIL: convFromToNullableT("conv.ovf.i1.un", "nuint", "sbyte")); conversions(sourceType: "nuint?", destType: "byte?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u1", "nuint", "byte"), expectedCheckedIL: convFromToNullableT("conv.ovf.u1.un", "nuint", "byte")); conversions(sourceType: "nuint?", destType: "short?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i2", "nuint", "short"), expectedCheckedIL: convFromToNullableT("conv.ovf.i2.un", "nuint", "short")); conversions(sourceType: "nuint?", destType: "ushort?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u2", "nuint", "ushort"), expectedCheckedIL: convFromToNullableT("conv.ovf.u2.un", "nuint", "ushort")); conversions(sourceType: "nuint?", destType: "int?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i4", "nuint", "int"), expectedCheckedIL: convFromToNullableT("conv.ovf.i4.un", "nuint", "int")); conversions(sourceType: "nuint?", destType: "uint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u4", "nuint", "uint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u4.un", "nuint", "uint")); conversions(sourceType: "nuint?", destType: "long?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u8", "nuint", "long"), expectedCheckedIL: convFromToNullableT("conv.ovf.i8.un", "nuint", "long")); conversions(sourceType: "nuint?", destType: "ulong?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.u8", "nuint", "ulong"), expectedExplicitIL: convFromToNullableT("conv.u8", "nuint", "ulong")); conversions(sourceType: "nuint?", destType: "float?", ImplicitNullableNumeric, expectedImplicitIL: convRUnFromToNullableT("conv.r4", "nuint", "float"), expectedExplicitIL: convRUnFromToNullableT("conv.r4", "nuint", "float"), null); conversions(sourceType: "nuint?", destType: "double?", ImplicitNullableNumeric, expectedImplicitIL: convRUnFromToNullableT("conv.r8", "nuint", "double"), expectedExplicitIL: convRUnFromToNullableT("conv.r8", "nuint", "double"), null); conversions(sourceType: "nuint?", destType: "decimal?", ImplicitNullableNumeric, @"{ // Code size 40 (0x28) .maxstack 1 .locals init (nuint? V_0, decimal? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nuint?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""decimal?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly nuint nuint?.GetValueOrDefault()"" IL_001c: conv.u8 IL_001d: call ""decimal decimal.op_Implicit(ulong)"" IL_0022: newobj ""decimal?..ctor(decimal)"" IL_0027: ret }", @"{ // Code size 40 (0x28) .maxstack 1 .locals init (nuint? V_0, decimal? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nuint?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""decimal?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly nuint nuint?.GetValueOrDefault()"" IL_001c: conv.u8 IL_001d: call ""decimal decimal.op_Implicit(ulong)"" IL_0022: newobj ""decimal?..ctor(decimal)"" IL_0027: ret }"); conversions(sourceType: "nuint?", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 34 (0x22) .maxstack 1 .locals init (nuint? V_0, nint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nuint?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""nint?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly nuint nuint?.GetValueOrDefault()"" IL_001c: newobj ""nint?..ctor(nint)"" IL_0021: ret } ", expectedCheckedIL: convFromToNullableT("conv.ovf.i.un", "nuint", "nint")); conversions(sourceType: "nuint?", destType: "System.UIntPtr?", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); // System.IntPtr to type conversions(sourceType: "System.IntPtr", destType: "object", Boxing, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: box ""nint"" IL_0006: ret }", @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: box ""nint"" IL_0006: ret }"); conversions(sourceType: "System.IntPtr", destType: "string", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "System.IntPtr", destType: "void*", ExplicitIntegerToPointer, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "System.IntPtr", destType: "delegate*<void>", ExplicitIntegerToPointer, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "System.IntPtr", destType: "void*", ExplicitIntegerToPointer, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "System.IntPtr", destType: "delegate*<void>", ExplicitIntegerToPointer, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "System.IntPtr", destType: "E", ExplicitEnumeration, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i4"), expectedCheckedIL: conv("conv.ovf.i4")); conversions(sourceType: "System.IntPtr", destType: "bool", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "System.IntPtr", destType: "char", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u2"), expectedCheckedIL: conv("conv.ovf.u2")); conversions(sourceType: "System.IntPtr", destType: "sbyte", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i1"), expectedCheckedIL: conv("conv.ovf.i1")); conversions(sourceType: "System.IntPtr", destType: "byte", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u1"), expectedCheckedIL: conv("conv.ovf.u1")); conversions(sourceType: "System.IntPtr", destType: "short", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i2"), expectedCheckedIL: conv("conv.ovf.i2")); conversions(sourceType: "System.IntPtr", destType: "ushort", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u2"), expectedCheckedIL: conv("conv.ovf.u2")); conversions(sourceType: "System.IntPtr", destType: "int", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i4"), expectedCheckedIL: conv("conv.ovf.i4")); conversions(sourceType: "System.IntPtr", destType: "uint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u4"), expectedCheckedIL: conv("conv.ovf.u4")); conversions(sourceType: "System.IntPtr", destType: "long", ImplicitNumeric, expectedImplicitIL: conv("conv.i8"), expectedExplicitIL: conv("conv.i8")); conversions(sourceType: "System.IntPtr", destType: "ulong", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i8"), expectedCheckedIL: conv("conv.ovf.u8")); conversions(sourceType: "System.IntPtr", destType: "float", ImplicitNumeric, expectedImplicitIL: conv("conv.r4"), expectedExplicitIL: conv("conv.r4")); conversions(sourceType: "System.IntPtr", destType: "double", ImplicitNumeric, expectedImplicitIL: conv("conv.r8"), expectedExplicitIL: conv("conv.r8")); conversions(sourceType: "System.IntPtr", destType: "decimal", ImplicitNumeric, @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarg.0 IL_0001: conv.i8 IL_0002: call ""decimal decimal.op_Implicit(long)"" IL_0007: ret }", @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarg.0 IL_0001: conv.i8 IL_0002: call ""decimal decimal.op_Implicit(long)"" IL_0007: ret }"); conversions(sourceType: "System.IntPtr", destType: "System.IntPtr", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); conversions(sourceType: "System.IntPtr", destType: "System.UIntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.u")); // System.IntPtr to nullable type conversions(sourceType: "System.IntPtr", destType: "E?", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i4", "E"), expectedCheckedIL: convToNullableT("conv.ovf.i4", "E")); conversions(sourceType: "System.IntPtr", destType: "bool?", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "System.IntPtr", destType: "char?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u2", "char"), expectedCheckedIL: convToNullableT("conv.ovf.u2", "char")); conversions(sourceType: "System.IntPtr", destType: "sbyte?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i1", "sbyte"), expectedCheckedIL: convToNullableT("conv.ovf.i1", "sbyte")); conversions(sourceType: "System.IntPtr", destType: "byte?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u1", "byte"), expectedCheckedIL: convToNullableT("conv.ovf.u1", "byte")); conversions(sourceType: "System.IntPtr", destType: "short?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i2", "short"), expectedCheckedIL: convToNullableT("conv.ovf.i2", "short")); conversions(sourceType: "System.IntPtr", destType: "ushort?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u2", "ushort"), expectedCheckedIL: convToNullableT("conv.ovf.u2", "ushort")); conversions(sourceType: "System.IntPtr", destType: "int?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i4", "int"), expectedCheckedIL: convToNullableT("conv.ovf.i4", "int")); conversions(sourceType: "System.IntPtr", destType: "uint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u4", "uint"), expectedCheckedIL: convToNullableT("conv.ovf.u4", "uint")); conversions(sourceType: "System.IntPtr", destType: "long?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.i8", "long"), expectedExplicitIL: convToNullableT("conv.i8", "long")); conversions(sourceType: "System.IntPtr", destType: "ulong?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i8", "ulong"), expectedCheckedIL: convToNullableT("conv.ovf.u8", "ulong")); conversions(sourceType: "System.IntPtr", destType: "float?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.r4", "float"), expectedExplicitIL: convToNullableT("conv.r4", "float"), null); conversions(sourceType: "System.IntPtr", destType: "double?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.r8", "double"), expectedExplicitIL: convToNullableT("conv.r8", "double"), null); conversions(sourceType: "System.IntPtr", destType: "decimal?", ImplicitNullableNumeric, @"{ // Code size 13 (0xd) .maxstack 1 IL_0000: ldarg.0 IL_0001: conv.i8 IL_0002: call ""decimal decimal.op_Implicit(long)"" IL_0007: newobj ""decimal?..ctor(decimal)"" IL_000c: ret }", @"{ // Code size 13 (0xd) .maxstack 1 IL_0000: ldarg.0 IL_0001: conv.i8 IL_0002: call ""decimal decimal.op_Implicit(long)"" IL_0007: newobj ""decimal?..ctor(decimal)"" IL_000c: ret }"); conversions(sourceType: "System.IntPtr", destType: "System.IntPtr?", ImplicitNullableIdentity, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret }", @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret }"); conversions(sourceType: "System.IntPtr", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nuint?..ctor(nuint)"" IL_0006: ret } ", expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); // nullable System.IntPtr to type conversions(sourceType: "System.IntPtr?", destType: "object", Boxing, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: box ""nint?"" IL_0006: ret }", @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: box ""nint?"" IL_0006: ret }"); conversions(sourceType: "System.IntPtr?", destType: "string", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "System.IntPtr?", destType: "void*", ExplicitUserDefined, expectedImplicitIL: null, expectedExplicitIL: convExplicitFromNullableT("nint", "void* nint.op_Explicit(nint)")); conversions(sourceType: "System.IntPtr?", destType: "delegate*<void>", ExplicitUserDefined, expectedImplicitIL: null, expectedExplicitIL: convExplicitFromNullableT("nint", "void* nint.op_Explicit(nint)")); conversions(sourceType: "System.IntPtr?", destType: "E", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i4", "nint"), expectedCheckedIL: convFromNullableT("conv.ovf.i4", "nint")); conversions(sourceType: "System.IntPtr?", destType: "bool", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "System.IntPtr?", destType: "char", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u2", "nint"), expectedCheckedIL: convFromNullableT("conv.ovf.u2", "nint")); conversions(sourceType: "System.IntPtr?", destType: "sbyte", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i1", "nint"), expectedCheckedIL: convFromNullableT("conv.ovf.i1", "nint")); conversions(sourceType: "System.IntPtr?", destType: "byte", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u1", "nint"), expectedCheckedIL: convFromNullableT("conv.ovf.u1", "nint")); conversions(sourceType: "System.IntPtr?", destType: "short", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i2", "nint"), expectedCheckedIL: convFromNullableT("conv.ovf.i2", "nint")); conversions(sourceType: "System.IntPtr?", destType: "ushort", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u2", "nint"), expectedCheckedIL: convFromNullableT("conv.ovf.u2", "nint")); conversions(sourceType: "System.IntPtr?", destType: "int", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i4", "nint"), expectedCheckedIL: convFromNullableT("conv.ovf.i4", "nint")); conversions(sourceType: "System.IntPtr?", destType: "uint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u4", "nint"), expectedCheckedIL: convFromNullableT("conv.ovf.u4", "nint")); conversions(sourceType: "System.IntPtr?", destType: "long", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i8", "nint")); conversions(sourceType: "System.IntPtr?", destType: "ulong", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i8", "nint"), expectedCheckedIL: convFromNullableT("conv.ovf.u8", "nint")); conversions(sourceType: "System.IntPtr?", destType: "float", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.r4", "nint")); conversions(sourceType: "System.IntPtr?", destType: "double", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.r8", "nint")); conversions(sourceType: "System.IntPtr?", destType: "decimal", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, @"{ // Code size 14 (0xe) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly nint nint?.Value.get"" IL_0007: conv.i8 IL_0008: call ""decimal decimal.op_Implicit(long)"" IL_000d: ret }"); conversions(sourceType: "System.IntPtr?", destType: "System.IntPtr", ExplicitNullableIdentity, expectedImplicitIL: null, @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly nint nint?.Value.get"" IL_0007: ret }"); conversions(sourceType: "System.IntPtr?", destType: "System.UIntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 8 (0x8) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly nint nint?.Value.get"" IL_0007: ret } ", expectedCheckedIL: convFromNullableT("conv.ovf.u", "nint")); // nullable System.IntPtr to nullable type conversions(sourceType: "System.IntPtr?", destType: "E?", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i4", "nint", "E"), expectedCheckedIL: convFromToNullableT("conv.ovf.i4", "nint", "E")); conversions(sourceType: "System.IntPtr?", destType: "bool?", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "System.IntPtr?", destType: "char?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u2", "nint", "char"), expectedCheckedIL: convFromToNullableT("conv.ovf.u2", "nint", "char")); conversions(sourceType: "System.IntPtr?", destType: "sbyte?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i1", "nint", "sbyte"), expectedCheckedIL: convFromToNullableT("conv.ovf.i1", "nint", "sbyte")); conversions(sourceType: "System.IntPtr?", destType: "byte?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u1", "nint", "byte"), expectedCheckedIL: convFromToNullableT("conv.ovf.u1", "nint", "byte")); conversions(sourceType: "System.IntPtr?", destType: "short?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i2", "nint", "short"), expectedCheckedIL: convFromToNullableT("conv.ovf.i2", "nint", "short")); conversions(sourceType: "System.IntPtr?", destType: "ushort?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u2", "nint", "ushort"), expectedCheckedIL: convFromToNullableT("conv.ovf.u2", "nint", "ushort")); conversions(sourceType: "System.IntPtr?", destType: "int?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i4", "nint", "int"), expectedCheckedIL: convFromToNullableT("conv.ovf.i4", "nint", "int")); conversions(sourceType: "System.IntPtr?", destType: "uint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u4", "nint", "uint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u4", "nint", "uint")); conversions(sourceType: "System.IntPtr?", destType: "long?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.i8", "nint", "long"), expectedExplicitIL: convFromToNullableT("conv.i8", "nint", "long")); conversions(sourceType: "System.IntPtr?", destType: "ulong?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i8", "nint", "ulong"), expectedCheckedIL: convFromToNullableT("conv.ovf.u8", "nint", "ulong")); conversions(sourceType: "System.IntPtr?", destType: "float?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.r4", "nint", "float"), expectedExplicitIL: convFromToNullableT("conv.r4", "nint", "float"), null); conversions(sourceType: "System.IntPtr?", destType: "double?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.r8", "nint", "double"), expectedExplicitIL: convFromToNullableT("conv.r8", "nint", "double"), null); conversions(sourceType: "System.IntPtr?", destType: "decimal?", ImplicitNullableNumeric, @"{ // Code size 40 (0x28) .maxstack 1 .locals init (nint? V_0, decimal? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nint?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""decimal?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly nint nint?.GetValueOrDefault()"" IL_001c: conv.i8 IL_001d: call ""decimal decimal.op_Implicit(long)"" IL_0022: newobj ""decimal?..ctor(decimal)"" IL_0027: ret }", @"{ // Code size 40 (0x28) .maxstack 1 .locals init (nint? V_0, decimal? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nint?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""decimal?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly nint nint?.GetValueOrDefault()"" IL_001c: conv.i8 IL_001d: call ""decimal decimal.op_Implicit(long)"" IL_0022: newobj ""decimal?..ctor(decimal)"" IL_0027: ret }"); conversions(sourceType: "System.IntPtr?", destType: "System.IntPtr?", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); conversions(sourceType: "System.IntPtr?", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 34 (0x22) .maxstack 1 .locals init (nint? V_0, nuint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nint?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""nuint?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly nint nint?.GetValueOrDefault()"" IL_001c: newobj ""nuint?..ctor(nuint)"" IL_0021: ret } ", expectedCheckedIL: convFromToNullableT("conv.ovf.u", "nint", "nuint")); // type to System.IntPtr conversions(sourceType: "object", destType: "System.IntPtr", Unboxing, expectedImplicitIL: null, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: unbox.any ""nint"" IL_0006: ret }"); conversions(sourceType: "string", destType: "System.IntPtr", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "void*", destType: "System.IntPtr", ExplicitPointerToInteger, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.i.un")); conversions(sourceType: "delegate*<void>", destType: "System.IntPtr", ExplicitPointerToInteger, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.i.un")); conversions(sourceType: "E", destType: "System.IntPtr", ExplicitEnumeration, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i")); conversions(sourceType: "bool", destType: "System.IntPtr", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "char", destType: "System.IntPtr", ImplicitNumeric, expectedImplicitIL: conv("conv.u"), expectedExplicitIL: conv("conv.u")); conversions(sourceType: "sbyte", destType: "System.IntPtr", ImplicitNumeric, expectedImplicitIL: conv("conv.i"), expectedExplicitIL: conv("conv.i")); conversions(sourceType: "byte", destType: "System.IntPtr", ImplicitNumeric, expectedImplicitIL: conv("conv.u"), expectedExplicitIL: conv("conv.u")); conversions(sourceType: "short", destType: "System.IntPtr", ImplicitNumeric, expectedImplicitIL: conv("conv.i"), expectedExplicitIL: conv("conv.i")); conversions(sourceType: "ushort", destType: "System.IntPtr", ImplicitNumeric, expectedImplicitIL: conv("conv.u"), expectedExplicitIL: conv("conv.u")); conversions(sourceType: "int", destType: "System.IntPtr", ImplicitNumeric, expectedImplicitIL: conv("conv.i"), expectedExplicitIL: conv("conv.i")); conversions(sourceType: "uint", destType: "System.IntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.i.un")); conversions(sourceType: "long", destType: "System.IntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.i")); conversions(sourceType: "ulong", destType: "System.IntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.i.un")); conversions(sourceType: "nint", destType: "System.IntPtr", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); conversions(sourceType: "nuint", destType: "System.IntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.i.un")); conversions(sourceType: "float", destType: "System.IntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.i")); conversions(sourceType: "double", destType: "System.IntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.i")); conversions(sourceType: "decimal", destType: "System.IntPtr", ExplicitNumeric, expectedImplicitIL: null, @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarg.0 IL_0001: call ""long decimal.op_Explicit(decimal)"" IL_0006: conv.i IL_0007: ret }", @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarg.0 IL_0001: call ""long decimal.op_Explicit(decimal)"" IL_0006: conv.ovf.i IL_0007: ret }"); conversions(sourceType: "System.UIntPtr", destType: "System.IntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.i.un")); // type to nullable System.IntPtr conversions(sourceType: "object", destType: "System.IntPtr?", Unboxing, expectedImplicitIL: null, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: unbox.any ""nint?"" IL_0006: ret }"); conversions(sourceType: "string", destType: "System.IntPtr?", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "void*", destType: "System.IntPtr?", ExplicitNullablePointerToInteger, expectedImplicitIL: null, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret }", @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarg.0 IL_0001: conv.ovf.i.un IL_0002: newobj ""nint?..ctor(nint)"" IL_0007: ret }"); conversions(sourceType: "delegate*<void>", destType: "System.IntPtr?", ExplicitNullablePointerToInteger, expectedImplicitIL: null, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret }", @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarg.0 IL_0001: conv.ovf.i.un IL_0002: newobj ""nint?..ctor(nint)"" IL_0007: ret }"); conversions(sourceType: "E", destType: "System.IntPtr?", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nint")); conversions(sourceType: "bool", destType: "System.IntPtr?", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "char", destType: "System.IntPtr?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.u", "nint"), expectedExplicitIL: convToNullableT("conv.u", "nint")); conversions(sourceType: "sbyte", destType: "System.IntPtr?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.i", "nint"), expectedExplicitIL: convToNullableT("conv.i", "nint")); conversions(sourceType: "byte", destType: "System.IntPtr?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.u", "nint"), expectedExplicitIL: convToNullableT("conv.u", "nint")); conversions(sourceType: "short", destType: "System.IntPtr?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.i", "nint"), expectedExplicitIL: convToNullableT("conv.i", "nint")); conversions(sourceType: "ushort", destType: "System.IntPtr?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.u", "nint"), expectedExplicitIL: convToNullableT("conv.u", "nint")); conversions(sourceType: "int", destType: "System.IntPtr?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.i", "nint"), expectedExplicitIL: convToNullableT("conv.i", "nint")); conversions(sourceType: "uint", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u", "nint"), expectedCheckedIL: convToNullableT("conv.ovf.i.un", "nint")); conversions(sourceType: "long", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nint"), expectedCheckedIL: convToNullableT("conv.ovf.i", "nint")); conversions(sourceType: "ulong", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nint"), expectedCheckedIL: convToNullableT("conv.ovf.i.un", "nint")); conversions(sourceType: "nint", destType: "System.IntPtr?", ImplicitNullableIdentity, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret }", @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret }"); conversions(sourceType: "nuint", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret } ", expectedCheckedIL: convToNullableT("conv.ovf.i.un", "nint")); conversions(sourceType: "float", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nint"), expectedCheckedIL: convToNullableT("conv.ovf.i", "nint")); conversions(sourceType: "double", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nint"), expectedCheckedIL: convToNullableT("conv.ovf.i", "nint")); conversions(sourceType: "decimal", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, @"{ // Code size 13 (0xd) .maxstack 1 IL_0000: ldarg.0 IL_0001: call ""long decimal.op_Explicit(decimal)"" IL_0006: conv.i IL_0007: newobj ""nint?..ctor(nint)"" IL_000c: ret }", @"{ // Code size 13 (0xd) .maxstack 1 IL_0000: ldarg.0 IL_0001: call ""long decimal.op_Explicit(decimal)"" IL_0006: conv.ovf.i IL_0007: newobj ""nint?..ctor(nint)"" IL_000c: ret }"); conversions(sourceType: "System.IntPtr", destType: "System.IntPtr?", ImplicitNullableIdentity, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret }", @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret }"); conversions(sourceType: "System.UIntPtr", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret } ", expectedCheckedIL: convToNullableT("conv.ovf.i.un", "nint")); // nullable type to System.IntPtr conversions(sourceType: "E?", destType: "System.IntPtr", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "E")); conversions(sourceType: "bool?", destType: "System.IntPtr", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "char?", destType: "System.IntPtr", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "char")); conversions(sourceType: "sbyte?", destType: "System.IntPtr", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "sbyte")); conversions(sourceType: "byte?", destType: "System.IntPtr", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "byte")); conversions(sourceType: "short?", destType: "System.IntPtr", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "short")); conversions(sourceType: "ushort?", destType: "System.IntPtr", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "ushort")); conversions(sourceType: "int?", destType: "System.IntPtr", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "int")); conversions(sourceType: "uint?", destType: "System.IntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "uint"), expectedCheckedIL: convFromNullableT("conv.ovf.i.un", "uint")); conversions(sourceType: "long?", destType: "System.IntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "long"), expectedCheckedIL: convFromNullableT("conv.ovf.i", "long")); conversions(sourceType: "ulong?", destType: "System.IntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "ulong"), expectedCheckedIL: convFromNullableT("conv.ovf.i.un", "ulong")); conversions(sourceType: "nint?", destType: "System.IntPtr", ExplicitNullableIdentity, expectedImplicitIL: null, @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly nint nint?.Value.get"" IL_0007: ret }"); conversions(sourceType: "nuint?", destType: "System.IntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 8 (0x8) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly nuint nuint?.Value.get"" IL_0007: ret } ", expectedCheckedIL: convFromNullableT("conv.ovf.i.un", "nuint")); conversions(sourceType: "float?", destType: "System.IntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "float"), expectedCheckedIL: convFromNullableT("conv.ovf.i", "float")); conversions(sourceType: "double?", destType: "System.IntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "double"), expectedCheckedIL: convFromNullableT("conv.ovf.i", "double")); conversions(sourceType: "decimal?", destType: "System.IntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, @"{ // Code size 14 (0xe) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly decimal decimal?.Value.get"" IL_0007: call ""long decimal.op_Explicit(decimal)"" IL_000c: conv.i IL_000d: ret }", @"{ // Code size 14 (0xe) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly decimal decimal?.Value.get"" IL_0007: call ""long decimal.op_Explicit(decimal)"" IL_000c: conv.ovf.i IL_000d: ret }"); conversions(sourceType: "System.IntPtr?", destType: "System.IntPtr", ExplicitNullableIdentity, expectedImplicitIL: null, @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly nint nint?.Value.get"" IL_0007: ret }"); conversions(sourceType: "System.UIntPtr?", destType: "System.IntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 8 (0x8) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly nuint nuint?.Value.get"" IL_0007: ret } ", expectedCheckedIL: convFromNullableT("conv.ovf.i.un", "nuint")); // nullable type to nullable System.IntPtr conversions(sourceType: "E?", destType: "System.IntPtr?", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "E", "nint")); conversions(sourceType: "bool?", destType: "System.IntPtr?", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "char?", destType: "System.IntPtr?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.u", "char", "nint"), expectedExplicitIL: convFromToNullableT("conv.u", "char", "nint")); conversions(sourceType: "sbyte?", destType: "System.IntPtr?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.i", "sbyte", "nint"), expectedExplicitIL: convFromToNullableT("conv.i", "sbyte", "nint")); conversions(sourceType: "byte?", destType: "System.IntPtr?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.u", "byte", "nint"), expectedExplicitIL: convFromToNullableT("conv.u", "byte", "nint")); conversions(sourceType: "short?", destType: "System.IntPtr?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.i", "short", "nint"), expectedExplicitIL: convFromToNullableT("conv.i", "short", "nint")); conversions(sourceType: "ushort?", destType: "System.IntPtr?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.u", "ushort", "nint"), expectedExplicitIL: convFromToNullableT("conv.u", "ushort", "nint")); conversions(sourceType: "int?", destType: "System.IntPtr?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.i", "int", "nint"), expectedExplicitIL: convFromToNullableT("conv.i", "int", "nint")); conversions(sourceType: "uint?", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "uint", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i.un", "uint", "nint")); conversions(sourceType: "long?", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "long", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i", "long", "nint")); conversions(sourceType: "ulong?", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "ulong", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i.un", "ulong", "nint")); conversions(sourceType: "nint?", destType: "System.IntPtr?", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); conversions(sourceType: "nuint?", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 34 (0x22) .maxstack 1 .locals init (nuint? V_0, nint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nuint?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""nint?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly nuint nuint?.GetValueOrDefault()"" IL_001c: newobj ""nint?..ctor(nint)"" IL_0021: ret } ", expectedCheckedIL: convFromToNullableT("conv.ovf.i.un", "nuint", "nint")); conversions(sourceType: "float?", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "float", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i", "float", "nint")); conversions(sourceType: "double?", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "double", "nint"), expectedCheckedIL: convFromToNullableT("conv.ovf.i", "double", "nint")); conversions(sourceType: "decimal?", destType: "System.IntPtr?", ExplicitNullableNumeric, null, @"{ // Code size 40 (0x28) .maxstack 1 .locals init (decimal? V_0, nint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool decimal?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""nint?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly decimal decimal?.GetValueOrDefault()"" IL_001c: call ""long decimal.op_Explicit(decimal)"" IL_0021: conv.i IL_0022: newobj ""nint?..ctor(nint)"" IL_0027: ret }", @"{ // Code size 40 (0x28) .maxstack 1 .locals init (decimal? V_0, nint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool decimal?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""nint?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly decimal decimal?.GetValueOrDefault()"" IL_001c: call ""long decimal.op_Explicit(decimal)"" IL_0021: conv.ovf.i IL_0022: newobj ""nint?..ctor(nint)"" IL_0027: ret }"); conversions(sourceType: "System.IntPtr?", destType: "System.IntPtr?", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); conversions(sourceType: "System.UIntPtr?", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 34 (0x22) .maxstack 1 .locals init (nuint? V_0, nint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nuint?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""nint?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly nuint nuint?.GetValueOrDefault()"" IL_001c: newobj ""nint?..ctor(nint)"" IL_0021: ret } ", expectedCheckedIL: convFromToNullableT("conv.ovf.i.un", "nuint", "nint")); // System.UIntPtr to type conversions(sourceType: "System.UIntPtr", destType: "object", Boxing, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: box ""nuint"" IL_0006: ret }", @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: box ""nuint"" IL_0006: ret }"); conversions(sourceType: "System.UIntPtr", destType: "string", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "System.UIntPtr", destType: "void*", ExplicitIntegerToPointer, expectedImplicitIL: null, expectedExplicitIL: convNone); conversions(sourceType: "System.UIntPtr", destType: "delegate*<void>", ExplicitIntegerToPointer, expectedImplicitIL: null, expectedExplicitIL: convNone); conversions(sourceType: "System.UIntPtr", destType: "E", ExplicitEnumeration, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i4"), expectedCheckedIL: conv("conv.ovf.i4.un")); conversions(sourceType: "System.UIntPtr", destType: "bool", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "System.UIntPtr", destType: "char", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u2"), expectedCheckedIL: conv("conv.ovf.u2.un")); conversions(sourceType: "System.UIntPtr", destType: "sbyte", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i1"), expectedCheckedIL: conv("conv.ovf.i1.un")); conversions(sourceType: "System.UIntPtr", destType: "byte", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u1"), expectedCheckedIL: conv("conv.ovf.u1.un")); conversions(sourceType: "System.UIntPtr", destType: "short", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i2"), expectedCheckedIL: conv("conv.ovf.i2.un")); conversions(sourceType: "System.UIntPtr", destType: "ushort", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u2"), expectedCheckedIL: conv("conv.ovf.u2.un")); conversions(sourceType: "System.UIntPtr", destType: "int", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i4"), expectedCheckedIL: conv("conv.ovf.i4.un")); conversions(sourceType: "System.UIntPtr", destType: "uint", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u4"), expectedCheckedIL: conv("conv.ovf.u4.un")); conversions(sourceType: "System.UIntPtr", destType: "long", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u8"), expectedCheckedIL: conv("conv.ovf.i8.un")); conversions(sourceType: "System.UIntPtr", destType: "ulong", ImplicitNumeric, expectedImplicitIL: conv("conv.u8"), expectedExplicitIL: conv("conv.u8")); conversions(sourceType: "System.UIntPtr", destType: "float", ImplicitNumeric, expectedImplicitIL: convRUn("conv.r4"), expectedExplicitIL: convRUn("conv.r4")); conversions(sourceType: "System.UIntPtr", destType: "double", ImplicitNumeric, expectedImplicitIL: convRUn("conv.r8"), expectedExplicitIL: convRUn("conv.r8")); conversions(sourceType: "System.UIntPtr", destType: "decimal", ImplicitNumeric, @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarg.0 IL_0001: conv.u8 IL_0002: call ""decimal decimal.op_Implicit(ulong)"" IL_0007: ret }", @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarg.0 IL_0001: conv.u8 IL_0002: call ""decimal decimal.op_Implicit(ulong)"" IL_0007: ret }"); conversions(sourceType: "System.UIntPtr", destType: "System.IntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.i.un")); conversions(sourceType: "System.UIntPtr", destType: "System.UIntPtr", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); // System.UIntPtr to nullable type conversions(sourceType: "System.UIntPtr", destType: "E?", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i4", "E"), expectedCheckedIL: convToNullableT("conv.ovf.i4.un", "E")); conversions(sourceType: "System.UIntPtr", destType: "bool?", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "System.UIntPtr", destType: "char?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u2", "char"), expectedCheckedIL: convToNullableT("conv.ovf.u2.un", "char")); conversions(sourceType: "System.UIntPtr", destType: "sbyte?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i1", "sbyte"), expectedCheckedIL: convToNullableT("conv.ovf.i1.un", "sbyte")); conversions(sourceType: "System.UIntPtr", destType: "byte?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u1", "byte"), expectedCheckedIL: convToNullableT("conv.ovf.u1.un", "byte")); conversions(sourceType: "System.UIntPtr", destType: "short?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i2", "short"), expectedCheckedIL: convToNullableT("conv.ovf.i2.un", "short")); conversions(sourceType: "System.UIntPtr", destType: "ushort?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u2", "ushort"), expectedCheckedIL: convToNullableT("conv.ovf.u2.un", "ushort")); conversions(sourceType: "System.UIntPtr", destType: "int?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i4", "int"), expectedCheckedIL: convToNullableT("conv.ovf.i4.un", "int")); conversions(sourceType: "System.UIntPtr", destType: "uint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u4", "uint"), expectedCheckedIL: convToNullableT("conv.ovf.u4.un", "uint")); conversions(sourceType: "System.UIntPtr", destType: "long?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u8", "long"), expectedCheckedIL: convToNullableT("conv.ovf.i8.un", "long")); conversions(sourceType: "System.UIntPtr", destType: "ulong?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.u8", "ulong"), expectedExplicitIL: convToNullableT("conv.u8", "ulong")); conversions(sourceType: "System.UIntPtr", destType: "float?", ImplicitNullableNumeric, expectedImplicitIL: convRUnToNullableT("conv.r4", "float"), expectedExplicitIL: convRUnToNullableT("conv.r4", "float"), null); conversions(sourceType: "System.UIntPtr", destType: "double?", ImplicitNullableNumeric, expectedImplicitIL: convRUnToNullableT("conv.r8", "double"), expectedExplicitIL: convRUnToNullableT("conv.r8", "double"), null); conversions(sourceType: "System.UIntPtr", destType: "decimal?", ImplicitNullableNumeric, @"{ // Code size 13 (0xd) .maxstack 1 IL_0000: ldarg.0 IL_0001: conv.u8 IL_0002: call ""decimal decimal.op_Implicit(ulong)"" IL_0007: newobj ""decimal?..ctor(decimal)"" IL_000c: ret }", @"{ // Code size 13 (0xd) .maxstack 1 IL_0000: ldarg.0 IL_0001: conv.u8 IL_0002: call ""decimal decimal.op_Implicit(ulong)"" IL_0007: newobj ""decimal?..ctor(decimal)"" IL_000c: ret }"); conversions(sourceType: "System.UIntPtr", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nint?..ctor(nint)"" IL_0006: ret } ", expectedCheckedIL: convToNullableT("conv.ovf.i.un", "nint")); conversions(sourceType: "System.UIntPtr", destType: "System.UIntPtr?", ImplicitNullableIdentity, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nuint?..ctor(nuint)"" IL_0006: ret }", @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nuint?..ctor(nuint)"" IL_0006: ret }"); // nullable System.UIntPtr to type conversions(sourceType: "System.UIntPtr?", destType: "object", Boxing, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: box ""nuint?"" IL_0006: ret }", @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: box ""nuint?"" IL_0006: ret }"); conversions(sourceType: "System.UIntPtr?", destType: "string", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "System.UIntPtr?", destType: "void*", ExplicitUserDefined, expectedImplicitIL: null, expectedExplicitIL: convExplicitFromNullableT("nuint", "void* nuint.op_Explicit(nuint)")); conversions(sourceType: "System.UIntPtr?", destType: "delegate*<void>", ExplicitUserDefined, expectedImplicitIL: null, expectedExplicitIL: convExplicitFromNullableT("nuint", "void* nuint.op_Explicit(nuint)")); conversions(sourceType: "System.UIntPtr?", destType: "E", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i4", "nuint"), expectedCheckedIL: convFromNullableT("conv.ovf.i4.un", "nuint")); conversions(sourceType: "System.UIntPtr?", destType: "bool", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "System.UIntPtr?", destType: "char", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u2", "nuint"), expectedCheckedIL: convFromNullableT("conv.ovf.u2.un", "nuint")); conversions(sourceType: "System.UIntPtr?", destType: "sbyte", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i1", "nuint"), expectedCheckedIL: convFromNullableT("conv.ovf.i1.un", "nuint")); conversions(sourceType: "System.UIntPtr?", destType: "byte", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u1", "nuint"), expectedCheckedIL: convFromNullableT("conv.ovf.u1.un", "nuint")); conversions(sourceType: "System.UIntPtr?", destType: "short", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i2", "nuint"), expectedCheckedIL: convFromNullableT("conv.ovf.i2.un", "nuint")); conversions(sourceType: "System.UIntPtr?", destType: "ushort", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u2", "nuint"), expectedCheckedIL: convFromNullableT("conv.ovf.u2.un", "nuint")); conversions(sourceType: "System.UIntPtr?", destType: "int", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i4", "nuint"), expectedCheckedIL: convFromNullableT("conv.ovf.i4.un", "nuint")); conversions(sourceType: "System.UIntPtr?", destType: "uint", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u4", "nuint"), expectedCheckedIL: convFromNullableT("conv.ovf.u4.un", "nuint")); conversions(sourceType: "System.UIntPtr?", destType: "long", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u8", "nuint"), expectedCheckedIL: convFromNullableT("conv.ovf.i8.un", "nuint")); conversions(sourceType: "System.UIntPtr?", destType: "ulong", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u8", "nuint")); conversions(sourceType: "System.UIntPtr?", destType: "float", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convRUnFromNullableT("conv.r4", "nuint")); conversions(sourceType: "System.UIntPtr?", destType: "double", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convRUnFromNullableT("conv.r8", "nuint")); conversions(sourceType: "System.UIntPtr?", destType: "decimal", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, @"{ // Code size 14 (0xe) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly nuint nuint?.Value.get"" IL_0007: conv.u8 IL_0008: call ""decimal decimal.op_Implicit(ulong)"" IL_000d: ret }"); conversions(sourceType: "System.UIntPtr?", destType: "System.IntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 8 (0x8) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly nuint nuint?.Value.get"" IL_0007: ret } ", expectedCheckedIL: convFromNullableT("conv.ovf.i.un", "nuint")); conversions(sourceType: "System.UIntPtr?", destType: "System.UIntPtr", ExplicitNullableIdentity, expectedImplicitIL: null, @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly nuint nuint?.Value.get"" IL_0007: ret }"); // nullable System.UIntPtr to nullable type conversions(sourceType: "System.UIntPtr?", destType: "E?", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i4", "nuint", "E"), expectedCheckedIL: convFromToNullableT("conv.ovf.i4.un", "nuint", "E")); conversions(sourceType: "System.UIntPtr?", destType: "bool?", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "System.UIntPtr?", destType: "char?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u2", "nuint", "char"), expectedCheckedIL: convFromToNullableT("conv.ovf.u2.un", "nuint", "char")); conversions(sourceType: "System.UIntPtr?", destType: "sbyte?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i1", "nuint", "sbyte"), expectedCheckedIL: convFromToNullableT("conv.ovf.i1.un", "nuint", "sbyte")); conversions(sourceType: "System.UIntPtr?", destType: "byte?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u1", "nuint", "byte"), expectedCheckedIL: convFromToNullableT("conv.ovf.u1.un", "nuint", "byte")); conversions(sourceType: "System.UIntPtr?", destType: "short?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i2", "nuint", "short"), expectedCheckedIL: convFromToNullableT("conv.ovf.i2.un", "nuint", "short")); conversions(sourceType: "System.UIntPtr?", destType: "ushort?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u2", "nuint", "ushort"), expectedCheckedIL: convFromToNullableT("conv.ovf.u2.un", "nuint", "ushort")); conversions(sourceType: "System.UIntPtr?", destType: "int?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i4", "nuint", "int"), expectedCheckedIL: convFromToNullableT("conv.ovf.i4.un", "nuint", "int")); conversions(sourceType: "System.UIntPtr?", destType: "uint?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u4", "nuint", "uint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u4.un", "nuint", "uint")); conversions(sourceType: "System.UIntPtr?", destType: "long?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u8", "nuint", "long"), expectedCheckedIL: convFromToNullableT("conv.ovf.i8.un", "nuint", "long")); conversions(sourceType: "System.UIntPtr?", destType: "ulong?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.u8", "nuint", "ulong"), expectedExplicitIL: convFromToNullableT("conv.u8", "nuint", "ulong")); conversions(sourceType: "System.UIntPtr?", destType: "float?", ImplicitNullableNumeric, expectedImplicitIL: convRUnFromToNullableT("conv.r4", "nuint", "float"), expectedExplicitIL: convRUnFromToNullableT("conv.r4", "nuint", "float"), null); conversions(sourceType: "System.UIntPtr?", destType: "double?", ImplicitNullableNumeric, expectedImplicitIL: convRUnFromToNullableT("conv.r8", "nuint", "double"), expectedExplicitIL: convRUnFromToNullableT("conv.r8", "nuint", "double"), null); conversions(sourceType: "System.UIntPtr?", destType: "decimal?", ImplicitNullableNumeric, @"{ // Code size 40 (0x28) .maxstack 1 .locals init (nuint? V_0, decimal? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nuint?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""decimal?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly nuint nuint?.GetValueOrDefault()"" IL_001c: conv.u8 IL_001d: call ""decimal decimal.op_Implicit(ulong)"" IL_0022: newobj ""decimal?..ctor(decimal)"" IL_0027: ret }", @"{ // Code size 40 (0x28) .maxstack 1 .locals init (nuint? V_0, decimal? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nuint?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""decimal?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly nuint nuint?.GetValueOrDefault()"" IL_001c: conv.u8 IL_001d: call ""decimal decimal.op_Implicit(ulong)"" IL_0022: newobj ""decimal?..ctor(decimal)"" IL_0027: ret }"); conversions(sourceType: "System.UIntPtr?", destType: "System.IntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 34 (0x22) .maxstack 1 .locals init (nuint? V_0, nint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nuint?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""nint?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly nuint nuint?.GetValueOrDefault()"" IL_001c: newobj ""nint?..ctor(nint)"" IL_0021: ret } ", expectedCheckedIL: convFromToNullableT("conv.ovf.i.un", "nuint", "nint")); conversions(sourceType: "System.UIntPtr?", destType: "System.UIntPtr?", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); // type to System.UIntPtr conversions(sourceType: "object", destType: "System.UIntPtr", Unboxing, expectedImplicitIL: null, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: unbox.any ""nuint"" IL_0006: ret }"); conversions(sourceType: "string", destType: "System.UIntPtr", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "void*", destType: "System.UIntPtr", ExplicitPointerToInteger, expectedImplicitIL: null, expectedExplicitIL: convNone); conversions(sourceType: "delegate*<void>", destType: "System.UIntPtr", ExplicitPointerToInteger, expectedImplicitIL: null, expectedExplicitIL: convNone); conversions(sourceType: "E", destType: "System.UIntPtr", ExplicitEnumeration, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "bool", destType: "System.UIntPtr", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "char", destType: "System.UIntPtr", ImplicitNumeric, expectedImplicitIL: conv("conv.u"), expectedExplicitIL: conv("conv.u")); conversions(sourceType: "sbyte", destType: "System.UIntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "byte", destType: "System.UIntPtr", ImplicitNumeric, expectedImplicitIL: conv("conv.u"), expectedExplicitIL: conv("conv.u")); conversions(sourceType: "short", destType: "System.UIntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "ushort", destType: "System.UIntPtr", ImplicitNumeric, expectedImplicitIL: conv("conv.u"), expectedExplicitIL: conv("conv.u")); conversions(sourceType: "int", destType: "System.UIntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "uint", destType: "System.UIntPtr", ImplicitNumeric, expectedImplicitIL: conv("conv.u"), expectedExplicitIL: conv("conv.u")); conversions(sourceType: "long", destType: "System.UIntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "ulong", destType: "System.UIntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.u.un")); conversions(sourceType: "nint", destType: "System.UIntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "nuint", destType: "System.UIntPtr", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); conversions(sourceType: "float", destType: "System.UIntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "double", destType: "System.UIntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: conv("conv.u"), expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "decimal", destType: "System.UIntPtr", ExplicitNumeric, expectedImplicitIL: null, @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarg.0 IL_0001: call ""ulong decimal.op_Explicit(decimal)"" IL_0006: conv.u IL_0007: ret }", @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarg.0 IL_0001: call ""ulong decimal.op_Explicit(decimal)"" IL_0006: conv.ovf.u.un IL_0007: ret }"); conversions(sourceType: "System.IntPtr", destType: "System.UIntPtr", ExplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.u")); conversions(sourceType: "System.UIntPtr", destType: "System.UIntPtr", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); // type to nullable System.UIntPtr conversions(sourceType: "object", destType: "System.UIntPtr?", Unboxing, expectedImplicitIL: null, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: unbox.any ""nuint?"" IL_0006: ret }"); conversions(sourceType: "string", destType: "System.UIntPtr?", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "void*", destType: "System.UIntPtr?", ExplicitNullablePointerToInteger, expectedImplicitIL: null, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nuint?..ctor(nuint)"" IL_0006: ret }"); conversions(sourceType: "delegate*<void>", destType: "System.UIntPtr?", ExplicitNullablePointerToInteger, expectedImplicitIL: null, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nuint?..ctor(nuint)"" IL_0006: ret }"); conversions(sourceType: "E", destType: "System.UIntPtr?", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); conversions(sourceType: "bool", destType: "System.UIntPtr?", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "char", destType: "System.UIntPtr?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.u", "nuint"), expectedExplicitIL: convToNullableT("conv.u", "nuint")); conversions(sourceType: "sbyte", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); conversions(sourceType: "byte", destType: "System.UIntPtr?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.u", "nuint"), expectedExplicitIL: convToNullableT("conv.u", "nuint")); conversions(sourceType: "short", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); conversions(sourceType: "ushort", destType: "System.UIntPtr?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.u", "nuint"), expectedExplicitIL: convToNullableT("conv.u", "nuint")); conversions(sourceType: "int", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.i", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); conversions(sourceType: "uint", destType: "System.UIntPtr?", ImplicitNullableNumeric, expectedImplicitIL: convToNullableT("conv.u", "nuint"), expectedExplicitIL: convToNullableT("conv.u", "nuint")); conversions(sourceType: "long", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); conversions(sourceType: "ulong", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u.un", "nuint")); conversions(sourceType: "nint", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nuint?..ctor(nuint)"" IL_0006: ret } ", expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); conversions(sourceType: "nuint", destType: "System.UIntPtr?", ImplicitNullableIdentity, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nuint?..ctor(nuint)"" IL_0006: ret }", @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nuint?..ctor(nuint)"" IL_0006: ret }"); conversions(sourceType: "float", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); conversions(sourceType: "double", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convToNullableT("conv.u", "nuint"), expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); conversions(sourceType: "decimal", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, @"{ // Code size 13 (0xd) .maxstack 1 IL_0000: ldarg.0 IL_0001: call ""ulong decimal.op_Explicit(decimal)"" IL_0006: conv.u IL_0007: newobj ""nuint?..ctor(nuint)"" IL_000c: ret }", @"{ // Code size 13 (0xd) .maxstack 1 IL_0000: ldarg.0 IL_0001: call ""ulong decimal.op_Explicit(decimal)"" IL_0006: conv.ovf.u.un IL_0007: newobj ""nuint?..ctor(nuint)"" IL_000c: ret }"); conversions(sourceType: "System.IntPtr", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nuint?..ctor(nuint)"" IL_0006: ret } ", expectedCheckedIL: convToNullableT("conv.ovf.u", "nuint")); conversions(sourceType: "System.UIntPtr", destType: "System.UIntPtr?", ImplicitNullableIdentity, @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nuint?..ctor(nuint)"" IL_0006: ret }", @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: newobj ""nuint?..ctor(nuint)"" IL_0006: ret }"); // nullable type to System.UIntPtr conversions(sourceType: "E?", destType: "System.UIntPtr", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "E"), expectedCheckedIL: convFromNullableT("conv.ovf.u", "E")); conversions(sourceType: "bool?", destType: "System.UIntPtr", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "char?", destType: "System.UIntPtr", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "char")); conversions(sourceType: "sbyte?", destType: "System.UIntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "sbyte"), expectedCheckedIL: convFromNullableT("conv.ovf.u", "sbyte")); conversions(sourceType: "byte?", destType: "System.UIntPtr", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "byte")); conversions(sourceType: "short?", destType: "System.UIntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "short"), expectedCheckedIL: convFromNullableT("conv.ovf.u", "short")); conversions(sourceType: "ushort?", destType: "System.UIntPtr", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "ushort")); conversions(sourceType: "int?", destType: "System.UIntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i", "int"), expectedCheckedIL: convFromNullableT("conv.ovf.u", "int")); conversions(sourceType: "uint?", destType: "System.UIntPtr", ExplicitNullableImplicitNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "uint")); conversions(sourceType: "long?", destType: "System.UIntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "long"), expectedCheckedIL: convFromNullableT("conv.ovf.u", "long")); conversions(sourceType: "ulong?", destType: "System.UIntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "ulong"), expectedCheckedIL: convFromNullableT("conv.ovf.u.un", "ulong")); conversions(sourceType: "nint?", destType: "System.UIntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 8 (0x8) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly nint nint?.Value.get"" IL_0007: ret } ", expectedCheckedIL: convFromNullableT("conv.ovf.u", "nint")); conversions(sourceType: "nuint?", destType: "System.UIntPtr", ExplicitNullableIdentity, expectedImplicitIL: null, @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly nuint nuint?.Value.get"" IL_0007: ret }"); conversions(sourceType: "float?", destType: "System.UIntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "float"), expectedCheckedIL: convFromNullableT("conv.ovf.u", "float")); conversions(sourceType: "double?", destType: "System.UIntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u", "double"), expectedCheckedIL: convFromNullableT("conv.ovf.u", "double")); conversions(sourceType: "decimal?", destType: "System.UIntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, @"{ // Code size 14 (0xe) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly decimal decimal?.Value.get"" IL_0007: call ""ulong decimal.op_Explicit(decimal)"" IL_000c: conv.u IL_000d: ret }", @"{ // Code size 14 (0xe) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly decimal decimal?.Value.get"" IL_0007: call ""ulong decimal.op_Explicit(decimal)"" IL_000c: conv.ovf.u.un IL_000d: ret }"); conversions(sourceType: "System.IntPtr?", destType: "System.UIntPtr", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 8 (0x8) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly nint nint?.Value.get"" IL_0007: ret } ", expectedCheckedIL: convFromNullableT("conv.ovf.u", "nint")); conversions(sourceType: "System.UIntPtr?", destType: "System.UIntPtr", ExplicitNullableIdentity, expectedImplicitIL: null, @"{ // Code size 8 (0x8) .maxstack 1 IL_0000: ldarga.s V_0 IL_0002: call ""readonly nuint nuint?.Value.get"" IL_0007: ret }"); // nullable type to nullable System.UIntPtr conversions(sourceType: "E?", destType: "System.UIntPtr?", ExplicitNullableEnumeration, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "E", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "E", "nuint")); conversions(sourceType: "bool?", destType: "System.UIntPtr?", NoConversion, expectedImplicitIL: null, expectedExplicitIL: null); conversions(sourceType: "char?", destType: "System.UIntPtr?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.u", "char", "nuint"), expectedExplicitIL: convFromToNullableT("conv.u", "char", "nuint")); conversions(sourceType: "sbyte?", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "sbyte", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "sbyte", "nuint")); conversions(sourceType: "byte?", destType: "System.UIntPtr?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.u", "byte", "nuint"), expectedExplicitIL: convFromToNullableT("conv.u", "byte", "nuint")); conversions(sourceType: "short?", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "short", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "short", "nuint")); conversions(sourceType: "ushort?", destType: "System.UIntPtr?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.u", "ushort", "nuint"), expectedExplicitIL: convFromToNullableT("conv.u", "ushort", "nuint")); conversions(sourceType: "int?", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.i", "int", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "int", "nuint")); conversions(sourceType: "uint?", destType: "System.UIntPtr?", ImplicitNullableNumeric, expectedImplicitIL: convFromToNullableT("conv.u", "uint", "nuint"), expectedExplicitIL: convFromToNullableT("conv.u", "uint", "nuint")); conversions(sourceType: "long?", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "long", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "long", "nuint")); conversions(sourceType: "ulong?", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "ulong", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u.un", "ulong", "nuint")); conversions(sourceType: "nint?", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 34 (0x22) .maxstack 1 .locals init (nint? V_0, nuint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nint?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""nuint?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly nint nint?.GetValueOrDefault()"" IL_001c: newobj ""nuint?..ctor(nuint)"" IL_0021: ret } ", expectedCheckedIL: convFromToNullableT("conv.ovf.u", "nint", "nuint")); conversions(sourceType: "nuint?", destType: "System.UIntPtr?", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); conversions(sourceType: "float?", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "float", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "float", "nuint")); conversions(sourceType: "double?", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: convFromToNullableT("conv.u", "double", "nuint"), expectedCheckedIL: convFromToNullableT("conv.ovf.u", "double", "nuint")); conversions(sourceType: "decimal?", destType: "System.UIntPtr?", ExplicitNullableNumeric, null, @"{ // Code size 40 (0x28) .maxstack 1 .locals init (decimal? V_0, nuint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool decimal?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""nuint?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly decimal decimal?.GetValueOrDefault()"" IL_001c: call ""ulong decimal.op_Explicit(decimal)"" IL_0021: conv.u IL_0022: newobj ""nuint?..ctor(nuint)"" IL_0027: ret }", @"{ // Code size 40 (0x28) .maxstack 1 .locals init (decimal? V_0, nuint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool decimal?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""nuint?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly decimal decimal?.GetValueOrDefault()"" IL_001c: call ""ulong decimal.op_Explicit(decimal)"" IL_0021: conv.ovf.u.un IL_0022: newobj ""nuint?..ctor(nuint)"" IL_0027: ret }"); conversions(sourceType: "System.IntPtr?", destType: "System.UIntPtr?", ExplicitNullableNumeric, expectedImplicitIL: null, expectedExplicitIL: @" { // Code size 34 (0x22) .maxstack 1 .locals init (nint? V_0, nuint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nint?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""nuint?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly nint nint?.GetValueOrDefault()"" IL_001c: newobj ""nuint?..ctor(nuint)"" IL_0021: ret } ", expectedCheckedIL: convFromToNullableT("conv.ovf.u", "nint", "nuint")); conversions(sourceType: "System.UIntPtr?", destType: "System.UIntPtr?", Identity, expectedImplicitIL: convNone, expectedExplicitIL: convNone); return; void convert(string sourceType, string destType, string expectedIL, bool useExplicitCast, bool useChecked, ConversionKind[] expectedConversions, ErrorCode expectedErrorCode) { bool useUnsafeContext = useUnsafe(sourceType) || useUnsafe(destType); string value = "value"; if (useExplicitCast) { value = $"({destType})value"; } var expectedDiagnostics = expectedErrorCode == 0 ? Array.Empty<DiagnosticDescription>() : new[] { Diagnostic(expectedErrorCode, value).WithArguments(AsNative(sourceType), AsNative(destType)) }; if (useChecked) { value = $"checked({value})"; } string source = $@"class Program {{ static {(useUnsafeContext ? "unsafe " : "")}{destType} Convert({sourceType} value) {{ return {value}; }} }} enum E {{ }} "; var comp = CreateCompilation(source, options: TestOptions.ReleaseDll.WithAllowUnsafe(useUnsafeContext), parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(expectedDiagnostics); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var expr = tree.GetRoot().DescendantNodes().OfType<ReturnStatementSyntax>().Single().Expression; var typeInfo = model.GetTypeInfo(expr); if (!useExplicitCast) { var destTypeSymbol = ((MethodSymbol)comp.GetMember("Program.Convert")).ReturnType.GetPublicSymbol(); AssertMatches(expectedConversions, model.ClassifyConversion(expr, destTypeSymbol)); Assert.Equal(AsNative(sourceType), typeInfo.Type.ToString()); Assert.Equal(AsNative(destType), typeInfo.ConvertedType.ToString()); } if (expectedIL != null) { var verifier = CompileAndVerify(comp, verify: useUnsafeContext ? Verification.Skipped : Verification.FailsPEVerify); verifier.VerifyIL("Program.Convert", expectedIL, ilFormat: ILFormat); } static bool useUnsafe(string type) => type == "void*" || type == "delegate*<void>"; } } [Fact] public void UnaryOperators() { static string getComplement(uint value) { object result = (IntPtr.Size == 4) ? (object)~value : (object)~(ulong)value; return result.ToString(); } void unifiedUnaryOp(string op, string opType, string expectedSymbol = null, string operand = null, string expectedResult = null, string expectedIL = "", DiagnosticDescription diagnostic = null) { Assert.True(opType is "System.IntPtr" or "System.UIntPtr" or "System.IntPtr?" or "System.UIntPtr?"); unaryOp(op, opType, expectedSymbol, operand, expectedResult, expectedIL, diagnostic); unaryOp(op, AsNative(opType), expectedSymbol, operand, expectedResult, expectedIL, diagnostic); } void unaryOp(string op, string opType, string expectedSymbol, string operand, string expectedResult, string expectedIL, DiagnosticDescription diagnostic) { operand ??= "default"; if (expectedSymbol == null && diagnostic == null) { diagnostic = Diagnostic(ErrorCode.ERR_BadUnaryOp, $"{op}operand").WithArguments(op, AsNative(opType)); } unaryOperator(op, opType, opType, expectedSymbol, operand, expectedResult, expectedIL, diagnostic != null ? new[] { diagnostic } : Array.Empty<DiagnosticDescription>()); } // unary operator+ unifiedUnaryOp("+", "System.IntPtr", "nint nint.op_UnaryPlus(nint value)", "3", "3", @"{ // Code size 2 (0x2) .maxstack 1 IL_0000: ldarg.0 IL_0001: ret }"); unifiedUnaryOp("+", "System.UIntPtr", "nuint nuint.op_UnaryPlus(nuint value)", "3", "3", @"{ // Code size 2 (0x2) .maxstack 1 IL_0000: ldarg.0 IL_0001: ret }"); // unary operator- unifiedUnaryOp("-", "System.IntPtr", "nint nint.op_UnaryNegation(nint value)", "3", "-3", @"{ // Code size 3 (0x3) .maxstack 1 IL_0000: ldarg.0 IL_0001: neg IL_0002: ret }"); unifiedUnaryOp("-", "System.UIntPtr"); // unary operator! unifiedUnaryOp("!", "System.IntPtr"); unifiedUnaryOp("!", "System.UIntPtr"); // unary operator~ unifiedUnaryOp("~", "System.IntPtr", "nint nint.op_OnesComplement(nint value)", "3", "-4", @"{ // Code size 3 (0x3) .maxstack 1 IL_0000: ldarg.0 IL_0001: not IL_0002: ret }"); unifiedUnaryOp("~", "System.UIntPtr", "nuint nuint.op_OnesComplement(nuint value)", "3", getComplement(3), @"{ // Code size 3 (0x3) .maxstack 1 IL_0000: ldarg.0 IL_0001: not IL_0002: ret }"); // lifted unary operator+ unifiedUnaryOp("+", "System.IntPtr?", "nint nint.op_UnaryPlus(nint value)", "3", "3", @"{ // Code size 34 (0x22) .maxstack 1 .locals init (nint? V_0, nint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nint?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""nint?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly nint nint?.GetValueOrDefault()"" IL_001c: newobj ""nint?..ctor(nint)"" IL_0021: ret }"); unifiedUnaryOp("+", "System.UIntPtr?", "nuint nuint.op_UnaryPlus(nuint value)", "3", "3", @"{ // Code size 34 (0x22) .maxstack 1 .locals init (nuint? V_0, nuint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nuint?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""nuint?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly nuint nuint?.GetValueOrDefault()"" IL_001c: newobj ""nuint?..ctor(nuint)"" IL_0021: ret }"); // lifted unary operator- unifiedUnaryOp("-", "System.IntPtr?", "nint nint.op_UnaryNegation(nint value)", "3", "-3", @"{ // Code size 35 (0x23) .maxstack 1 .locals init (nint? V_0, nint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nint?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""nint?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly nint nint?.GetValueOrDefault()"" IL_001c: neg IL_001d: newobj ""nint?..ctor(nint)"" IL_0022: ret }"); // Reporting ERR_AmbigUnaryOp for `-(nuint?)value` is inconsistent with the ERR_BadUnaryOp reported // for `-(nuint)value`, but that difference in behavior is consistent with the pair of errors reported for // `-(ulong?)value` and `-(ulong)value`. See the "Special case" in Binder.UnaryOperatorOverloadResolution() // which handles ulong but not ulong?. unifiedUnaryOp("-", "System.UIntPtr?", null, null, null, null, Diagnostic(ErrorCode.ERR_AmbigUnaryOp, "-operand").WithArguments("-", "nuint?")); // lifted unary operator! unifiedUnaryOp("!", "System.IntPtr?"); unifiedUnaryOp("!", "System.UIntPtr?"); // lifted unary operator~ unifiedUnaryOp("~", "System.IntPtr?", "nint nint.op_OnesComplement(nint value)", "3", "-4", @"{ // Code size 35 (0x23) .maxstack 1 .locals init (nint? V_0, nint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nint?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""nint?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly nint nint?.GetValueOrDefault()"" IL_001c: not IL_001d: newobj ""nint?..ctor(nint)"" IL_0022: ret }"); unifiedUnaryOp("~", "System.UIntPtr?", "nuint nuint.op_OnesComplement(nuint value)", "3", getComplement(3), @"{ // Code size 35 (0x23) .maxstack 1 .locals init (nuint? V_0, nuint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nuint?.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""nuint?"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly nuint nuint?.GetValueOrDefault()"" IL_001c: not IL_001d: newobj ""nuint?..ctor(nuint)"" IL_0022: ret }"); void unaryOperator(string op, string opType, string resultType, string expectedSymbol, string operand, string expectedResult, string expectedIL, DiagnosticDescription[] expectedDiagnostics) { string source = $@"class Program {{ static {resultType} Evaluate({opType} operand) {{ return {op}operand; }} static void Main() {{ System.Console.WriteLine(Evaluate({operand})); }} }}"; var comp = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(expectedDiagnostics); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var expr = tree.GetRoot().DescendantNodes().OfType<PrefixUnaryExpressionSyntax>().Single(); var symbolInfo = model.GetSymbolInfo(expr); Assert.Equal(expectedSymbol, symbolInfo.Symbol?.ToDisplayString(TestFormat.WithMiscellaneousOptions(SymbolDisplayMiscellaneousOptions.UseSpecialTypes))); if (expectedDiagnostics.Length == 0) { var verifier = CompileAndVerify(comp, verify: Verification.FailsPEVerify, expectedOutput: IncludeExpectedOutput(expectedResult)); verifier.VerifyIL("Program.Evaluate", expectedIL, ilFormat: ILFormat); } } } [Fact] public void IncrementOperators() { void unifiedIncrementOps(string op, string opType, string expectedSymbol = null, bool useChecked = false, string values = null, string expectedResult = null, string expectedIL = "", string expectedLiftedIL = "", DiagnosticDescription diagnostic = null) { Assert.True(opType is "System.IntPtr" or "System.UIntPtr" or "System.IntPtr?" or "System.UIntPtr?"); incrementOps(op, opType, expectedSymbol, useChecked, values, expectedResult, expectedIL, expectedLiftedIL, diagnostic); incrementOps(op, AsNative(opType), expectedSymbol, useChecked, values, expectedResult, expectedIL, expectedLiftedIL, diagnostic); } void incrementOps(string op, string opType, string expectedSymbol, bool useChecked, string values, string expectedResult, string expectedIL, string expectedLiftedIL, DiagnosticDescription diagnostic) { incrementOperator(op, opType, isPrefix: true, expectedSymbol, useChecked, values, expectedResult, expectedIL, getDiagnostics(opType, isPrefix: true, diagnostic)); incrementOperator(op, opType, isPrefix: false, expectedSymbol, useChecked, values, expectedResult, expectedIL, getDiagnostics(opType, isPrefix: false, diagnostic)); opType += "?"; incrementOperator(op, opType, isPrefix: true, expectedSymbol, useChecked, values, expectedResult, expectedLiftedIL, getDiagnostics(opType, isPrefix: true, diagnostic)); incrementOperator(op, opType, isPrefix: false, expectedSymbol, useChecked, values, expectedResult, expectedLiftedIL, getDiagnostics(opType, isPrefix: false, diagnostic)); DiagnosticDescription[] getDiagnostics(string opType, bool isPrefix, DiagnosticDescription diagnostic) { if (expectedSymbol == null && diagnostic == null) { diagnostic = Diagnostic(ErrorCode.ERR_BadUnaryOp, isPrefix ? op + "operand" : "operand" + op).WithArguments(op, opType); } return diagnostic != null ? new[] { diagnostic } : Array.Empty<DiagnosticDescription>(); } } unifiedIncrementOps("++", "System.IntPtr", "nint nint.op_Increment(nint value)", useChecked: false, values: $"{int.MinValue}, -1, 0, {int.MaxValue - 1}, {int.MaxValue}", expectedResult: $"-2147483647, 0, 1, 2147483647, {(IntPtr.Size == 4 ? "-2147483648" : "2147483648")}", @"{ // Code size 7 (0x7) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldc.i4.1 IL_0002: add IL_0003: starg.s V_0 IL_0005: ldarg.0 IL_0006: ret }", @"{ // Code size 40 (0x28) .maxstack 2 .locals init (nint? V_0, nint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nint?.HasValue.get"" IL_0009: brtrue.s IL_0016 IL_000b: ldloca.s V_1 IL_000d: initobj ""nint?"" IL_0013: ldloc.1 IL_0014: br.s IL_0024 IL_0016: ldloca.s V_0 IL_0018: call ""readonly nint nint?.GetValueOrDefault()"" IL_001d: ldc.i4.1 IL_001e: add IL_001f: newobj ""nint?..ctor(nint)"" IL_0024: starg.s V_0 IL_0026: ldarg.0 IL_0027: ret }"); unifiedIncrementOps("++", "System.UIntPtr", "nuint nuint.op_Increment(nuint value)", useChecked: false, values: $"0, {int.MaxValue}, {uint.MaxValue - 1}, {uint.MaxValue}", expectedResult: $"1, 2147483648, 4294967295, {(IntPtr.Size == 4 ? "0" : "4294967296")}", @"{ // Code size 7 (0x7) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldc.i4.1 IL_0002: add IL_0003: starg.s V_0 IL_0005: ldarg.0 IL_0006: ret }", @"{ // Code size 40 (0x28) .maxstack 2 .locals init (nuint? V_0, nuint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nuint?.HasValue.get"" IL_0009: brtrue.s IL_0016 IL_000b: ldloca.s V_1 IL_000d: initobj ""nuint?"" IL_0013: ldloc.1 IL_0014: br.s IL_0024 IL_0016: ldloca.s V_0 IL_0018: call ""readonly nuint nuint?.GetValueOrDefault()"" IL_001d: ldc.i4.1 IL_001e: add IL_001f: newobj ""nuint?..ctor(nuint)"" IL_0024: starg.s V_0 IL_0026: ldarg.0 IL_0027: ret }"); unifiedIncrementOps("--", "System.IntPtr", "nint nint.op_Decrement(nint value)", useChecked: false, values: $"{int.MinValue}, {int.MinValue + 1}, 0, 1, {int.MaxValue}", expectedResult: $"{(IntPtr.Size == 4 ? "2147483647" : "-2147483649")}, -2147483648, -1, 0, 2147483646", @"{ // Code size 7 (0x7) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldc.i4.1 IL_0002: sub IL_0003: starg.s V_0 IL_0005: ldarg.0 IL_0006: ret }", @"{ // Code size 40 (0x28) .maxstack 2 .locals init (nint? V_0, nint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nint?.HasValue.get"" IL_0009: brtrue.s IL_0016 IL_000b: ldloca.s V_1 IL_000d: initobj ""nint?"" IL_0013: ldloc.1 IL_0014: br.s IL_0024 IL_0016: ldloca.s V_0 IL_0018: call ""readonly nint nint?.GetValueOrDefault()"" IL_001d: ldc.i4.1 IL_001e: sub IL_001f: newobj ""nint?..ctor(nint)"" IL_0024: starg.s V_0 IL_0026: ldarg.0 IL_0027: ret }"); unifiedIncrementOps("--", "System.UIntPtr", "nuint nuint.op_Decrement(nuint value)", useChecked: false, values: $"0, 1, {uint.MaxValue}", expectedResult: $"{(IntPtr.Size == 4 ? uint.MaxValue.ToString() : ulong.MaxValue.ToString())}, 0, 4294967294", @"{ // Code size 7 (0x7) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldc.i4.1 IL_0002: sub IL_0003: starg.s V_0 IL_0005: ldarg.0 IL_0006: ret }", @"{ // Code size 40 (0x28) .maxstack 2 .locals init (nuint? V_0, nuint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nuint?.HasValue.get"" IL_0009: brtrue.s IL_0016 IL_000b: ldloca.s V_1 IL_000d: initobj ""nuint?"" IL_0013: ldloc.1 IL_0014: br.s IL_0024 IL_0016: ldloca.s V_0 IL_0018: call ""readonly nuint nuint?.GetValueOrDefault()"" IL_001d: ldc.i4.1 IL_001e: sub IL_001f: newobj ""nuint?..ctor(nuint)"" IL_0024: starg.s V_0 IL_0026: ldarg.0 IL_0027: ret }"); unifiedIncrementOps("++", "System.IntPtr", "nint nint.op_CheckedIncrement(nint value)", useChecked: true, values: $"{int.MinValue}, -1, 0, {int.MaxValue - 1}, {int.MaxValue}", expectedResult: $"-2147483647, 0, 1, 2147483647, {(IntPtr.Size == 4 ? "System.OverflowException" : "2147483648")}", @"{ // Code size 7 (0x7) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldc.i4.1 IL_0002: add.ovf IL_0003: starg.s V_0 IL_0005: ldarg.0 IL_0006: ret }", @"{ // Code size 40 (0x28) .maxstack 2 .locals init (nint? V_0, nint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nint?.HasValue.get"" IL_0009: brtrue.s IL_0016 IL_000b: ldloca.s V_1 IL_000d: initobj ""nint?"" IL_0013: ldloc.1 IL_0014: br.s IL_0024 IL_0016: ldloca.s V_0 IL_0018: call ""readonly nint nint?.GetValueOrDefault()"" IL_001d: ldc.i4.1 IL_001e: add.ovf IL_001f: newobj ""nint?..ctor(nint)"" IL_0024: starg.s V_0 IL_0026: ldarg.0 IL_0027: ret }"); unifiedIncrementOps("++", "System.UIntPtr", "nuint nuint.op_CheckedIncrement(nuint value)", useChecked: true, values: $"0, {int.MaxValue}, {uint.MaxValue - 1}, {uint.MaxValue}", expectedResult: $"1, 2147483648, 4294967295, {(IntPtr.Size == 4 ? "System.OverflowException" : "4294967296")}", @"{ // Code size 7 (0x7) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldc.i4.1 IL_0002: add.ovf.un IL_0003: starg.s V_0 IL_0005: ldarg.0 IL_0006: ret }", @"{ // Code size 40 (0x28) .maxstack 2 .locals init (nuint? V_0, nuint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nuint?.HasValue.get"" IL_0009: brtrue.s IL_0016 IL_000b: ldloca.s V_1 IL_000d: initobj ""nuint?"" IL_0013: ldloc.1 IL_0014: br.s IL_0024 IL_0016: ldloca.s V_0 IL_0018: call ""readonly nuint nuint?.GetValueOrDefault()"" IL_001d: ldc.i4.1 IL_001e: add.ovf.un IL_001f: newobj ""nuint?..ctor(nuint)"" IL_0024: starg.s V_0 IL_0026: ldarg.0 IL_0027: ret }"); unifiedIncrementOps("--", "System.IntPtr", "nint nint.op_CheckedDecrement(nint value)", useChecked: true, values: $"{int.MinValue}, {int.MinValue + 1}, 0, 1, {int.MaxValue}", expectedResult: $"{(IntPtr.Size == 4 ? "System.OverflowException" : "-2147483649")}, -2147483648, -1, 0, 2147483646", @"{ // Code size 7 (0x7) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldc.i4.1 IL_0002: sub.ovf IL_0003: starg.s V_0 IL_0005: ldarg.0 IL_0006: ret }", @"{ // Code size 40 (0x28) .maxstack 2 .locals init (nint? V_0, nint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nint?.HasValue.get"" IL_0009: brtrue.s IL_0016 IL_000b: ldloca.s V_1 IL_000d: initobj ""nint?"" IL_0013: ldloc.1 IL_0014: br.s IL_0024 IL_0016: ldloca.s V_0 IL_0018: call ""readonly nint nint?.GetValueOrDefault()"" IL_001d: ldc.i4.1 IL_001e: sub.ovf IL_001f: newobj ""nint?..ctor(nint)"" IL_0024: starg.s V_0 IL_0026: ldarg.0 IL_0027: ret }"); unifiedIncrementOps("--", "System.UIntPtr", "nuint nuint.op_CheckedDecrement(nuint value)", useChecked: true, values: $"0, 1, {uint.MaxValue}", expectedResult: $"System.OverflowException, 0, 4294967294", @"{ // Code size 7 (0x7) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldc.i4.1 IL_0002: sub.ovf.un IL_0003: starg.s V_0 IL_0005: ldarg.0 IL_0006: ret }", @"{ // Code size 40 (0x28) .maxstack 2 .locals init (nuint? V_0, nuint? V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool nuint?.HasValue.get"" IL_0009: brtrue.s IL_0016 IL_000b: ldloca.s V_1 IL_000d: initobj ""nuint?"" IL_0013: ldloc.1 IL_0014: br.s IL_0024 IL_0016: ldloca.s V_0 IL_0018: call ""readonly nuint nuint?.GetValueOrDefault()"" IL_001d: ldc.i4.1 IL_001e: sub.ovf.un IL_001f: newobj ""nuint?..ctor(nuint)"" IL_0024: starg.s V_0 IL_0026: ldarg.0 IL_0027: ret }"); void incrementOperator(string op, string opType, bool isPrefix, string expectedSymbol, bool useChecked, string values, string expectedResult, string expectedIL, DiagnosticDescription[] expectedDiagnostics) { var source = $@"using System; class Program {{ static {opType} Evaluate({opType} operand) {{ {(useChecked ? "checked" : "unchecked")} {{ {(isPrefix ? op + "operand" : "operand" + op)}; return operand; }} }} static void EvaluateAndReport({opType} operand) {{ object result; try {{ result = Evaluate(operand); }} catch (Exception e) {{ result = e.GetType(); }} Console.Write(result); }} static void Main() {{ bool separator = false; foreach (var value in new {opType}[] {{ {values} }}) {{ if (separator) Console.Write("", ""); separator = true; EvaluateAndReport(value); }} }} }}"; var comp = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(expectedDiagnostics); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var kind = (op == "++") ? isPrefix ? SyntaxKind.PreIncrementExpression : SyntaxKind.PostIncrementExpression : isPrefix ? SyntaxKind.PreDecrementExpression : SyntaxKind.PostDecrementExpression; var expr = tree.GetRoot().DescendantNodes().Single(n => n.Kind() == kind); var symbolInfo = model.GetSymbolInfo(expr); Assert.Equal(expectedSymbol, symbolInfo.Symbol?.ToDisplayString(TestFormat.WithMiscellaneousOptions(SymbolDisplayMiscellaneousOptions.UseSpecialTypes))); if (expectedDiagnostics.Length == 0) { var verifier = CompileAndVerify(comp, verify: Verification.FailsPEVerify, expectedOutput: IncludeExpectedOutput(expectedResult)); verifier.VerifyIL("Program.Evaluate", expectedIL, ilFormat: ILFormat); } } } [Fact] public void IncrementOperators_RefOperand() { void unifiedIncrementOps(string op, string opType, string expectedSymbol = null, string values = null, string expectedResult = null, string expectedIL = "", string expectedLiftedIL = "", DiagnosticDescription diagnostic = null) { Assert.True(opType is "System.IntPtr" or "System.UIntPtr" or "System.IntPtr?" or "System.UIntPtr?"); incrementOps(op, opType, expectedSymbol, values, expectedResult, expectedIL, expectedLiftedIL, diagnostic); incrementOps(op, AsNative(opType), expectedSymbol, values, expectedResult, expectedIL, expectedLiftedIL, diagnostic); } void incrementOps(string op, string opType, string expectedSymbol = null, string values = null, string expectedResult = null, string expectedIL = "", string expectedLiftedIL = "", DiagnosticDescription diagnostic = null) { incrementOperator(op, opType, expectedSymbol, values, expectedResult, expectedIL, getDiagnostics(opType, diagnostic)); opType += "?"; incrementOperator(op, opType, expectedSymbol, values, expectedResult, expectedLiftedIL, getDiagnostics(opType, diagnostic)); DiagnosticDescription[] getDiagnostics(string opType, DiagnosticDescription diagnostic) { if (expectedSymbol == null && diagnostic == null) { diagnostic = Diagnostic(ErrorCode.ERR_BadUnaryOp, op + "operand").WithArguments(op, opType); } return diagnostic != null ? new[] { diagnostic } : Array.Empty<DiagnosticDescription>(); } } unifiedIncrementOps("++", "System.IntPtr", "nint nint.op_Increment(nint value)", values: $"{int.MinValue}, -1, 0, {int.MaxValue - 1}, {int.MaxValue}", expectedResult: $"-2147483647, 0, 1, 2147483647, {(IntPtr.Size == 4 ? "-2147483648" : "2147483648")}", @"{ // Code size 7 (0x7) .maxstack 3 IL_0000: ldarg.0 IL_0001: ldarg.0 IL_0002: ldind.i IL_0003: ldc.i4.1 IL_0004: add IL_0005: stind.i IL_0006: ret }", @"{ // Code size 48 (0x30) .maxstack 3 .locals init (nint? V_0, nint? V_1) IL_0000: ldarg.0 IL_0001: ldarg.0 IL_0002: ldobj ""nint?"" IL_0007: stloc.0 IL_0008: ldloca.s V_0 IL_000a: call ""readonly bool nint?.HasValue.get"" IL_000f: brtrue.s IL_001c IL_0011: ldloca.s V_1 IL_0013: initobj ""nint?"" IL_0019: ldloc.1 IL_001a: br.s IL_002a IL_001c: ldloca.s V_0 IL_001e: call ""readonly nint nint?.GetValueOrDefault()"" IL_0023: ldc.i4.1 IL_0024: add IL_0025: newobj ""nint?..ctor(nint)"" IL_002a: stobj ""nint?"" IL_002f: ret }"); unifiedIncrementOps("++", "System.UIntPtr", "nuint nuint.op_Increment(nuint value)", values: $"0, {int.MaxValue}, {uint.MaxValue - 1}, {uint.MaxValue}", expectedResult: $"1, 2147483648, 4294967295, {(IntPtr.Size == 4 ? "0" : "4294967296")}", @"{ // Code size 7 (0x7) .maxstack 3 IL_0000: ldarg.0 IL_0001: ldarg.0 IL_0002: ldind.i IL_0003: ldc.i4.1 IL_0004: add IL_0005: stind.i IL_0006: ret }", @"{ // Code size 48 (0x30) .maxstack 3 .locals init (nuint? V_0, nuint? V_1) IL_0000: ldarg.0 IL_0001: ldarg.0 IL_0002: ldobj ""nuint?"" IL_0007: stloc.0 IL_0008: ldloca.s V_0 IL_000a: call ""readonly bool nuint?.HasValue.get"" IL_000f: brtrue.s IL_001c IL_0011: ldloca.s V_1 IL_0013: initobj ""nuint?"" IL_0019: ldloc.1 IL_001a: br.s IL_002a IL_001c: ldloca.s V_0 IL_001e: call ""readonly nuint nuint?.GetValueOrDefault()"" IL_0023: ldc.i4.1 IL_0024: add IL_0025: newobj ""nuint?..ctor(nuint)"" IL_002a: stobj ""nuint?"" IL_002f: ret }"); unifiedIncrementOps("--", "System.IntPtr", "nint nint.op_Decrement(nint value)", values: $"{int.MinValue}, {int.MinValue + 1}, 0, 1, {int.MaxValue}", expectedResult: $"{(IntPtr.Size == 4 ? "2147483647" : "-2147483649")}, -2147483648, -1, 0, 2147483646", @"{ // Code size 7 (0x7) .maxstack 3 IL_0000: ldarg.0 IL_0001: ldarg.0 IL_0002: ldind.i IL_0003: ldc.i4.1 IL_0004: sub IL_0005: stind.i IL_0006: ret }", @"{ // Code size 48 (0x30) .maxstack 3 .locals init (nint? V_0, nint? V_1) IL_0000: ldarg.0 IL_0001: ldarg.0 IL_0002: ldobj ""nint?"" IL_0007: stloc.0 IL_0008: ldloca.s V_0 IL_000a: call ""readonly bool nint?.HasValue.get"" IL_000f: brtrue.s IL_001c IL_0011: ldloca.s V_1 IL_0013: initobj ""nint?"" IL_0019: ldloc.1 IL_001a: br.s IL_002a IL_001c: ldloca.s V_0 IL_001e: call ""readonly nint nint?.GetValueOrDefault()"" IL_0023: ldc.i4.1 IL_0024: sub IL_0025: newobj ""nint?..ctor(nint)"" IL_002a: stobj ""nint?"" IL_002f: ret }"); unifiedIncrementOps("--", "System.UIntPtr", "nuint nuint.op_Decrement(nuint value)", values: $"0, 1, {uint.MaxValue}", expectedResult: $"{(IntPtr.Size == 4 ? uint.MaxValue.ToString() : ulong.MaxValue.ToString())}, 0, 4294967294", @"{ // Code size 7 (0x7) .maxstack 3 IL_0000: ldarg.0 IL_0001: ldarg.0 IL_0002: ldind.i IL_0003: ldc.i4.1 IL_0004: sub IL_0005: stind.i IL_0006: ret }", @"{ // Code size 48 (0x30) .maxstack 3 .locals init (nuint? V_0, nuint? V_1) IL_0000: ldarg.0 IL_0001: ldarg.0 IL_0002: ldobj ""nuint?"" IL_0007: stloc.0 IL_0008: ldloca.s V_0 IL_000a: call ""readonly bool nuint?.HasValue.get"" IL_000f: brtrue.s IL_001c IL_0011: ldloca.s V_1 IL_0013: initobj ""nuint?"" IL_0019: ldloc.1 IL_001a: br.s IL_002a IL_001c: ldloca.s V_0 IL_001e: call ""readonly nuint nuint?.GetValueOrDefault()"" IL_0023: ldc.i4.1 IL_0024: sub IL_0025: newobj ""nuint?..ctor(nuint)"" IL_002a: stobj ""nuint?"" IL_002f: ret }"); void incrementOperator(string op, string opType, string expectedSymbol, string values, string expectedResult, string expectedIL, DiagnosticDescription[] expectedDiagnostics) { string source = $@"using System; class Program {{ static void Evaluate(ref {opType} operand) {{ {op}operand; }} static void EvaluateAndReport({opType} operand) {{ object result; try {{ Evaluate(ref operand); result = operand; }} catch (Exception e) {{ result = e.GetType(); }} Console.Write(result); }} static void Main() {{ bool separator = false; foreach (var value in new {opType}[] {{ {values} }}) {{ if (separator) Console.Write("", ""); separator = true; EvaluateAndReport(value); }} }} }}"; var comp = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(expectedDiagnostics); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var kind = (op == "++") ? SyntaxKind.PreIncrementExpression : SyntaxKind.PreDecrementExpression; var expr = tree.GetRoot().DescendantNodes().Single(n => n.Kind() == kind); var symbolInfo = model.GetSymbolInfo(expr); Assert.Equal(expectedSymbol, symbolInfo.Symbol?.ToDisplayString(TestFormat.WithMiscellaneousOptions(SymbolDisplayMiscellaneousOptions.UseSpecialTypes))); if (expectedDiagnostics.Length == 0) { var verifier = CompileAndVerify(comp, verify: Verification.FailsPEVerify, expectedOutput: IncludeExpectedOutput(expectedResult)); verifier.VerifyIL("Program.Evaluate", expectedIL, ilFormat: ILFormat); } } } [Fact] public void UnaryOperators_UserDefined() { string sourceA = @"namespace System { public class Object { } public class String { } public abstract class ValueType { } public struct Void { } public struct Boolean { } public struct Int32 { } public struct Enum { } public class Attribute { } public class AttributeUsageAttribute : Attribute { public AttributeUsageAttribute(AttributeTargets validOn) { } public bool AllowMultiple { get; set; } public bool Inherited { get; set; } } public enum AttributeTargets { } public struct IntPtr { public static IntPtr operator-(IntPtr i) => i; } }"; string sourceB = @"class Program { static System.IntPtr F1(System.IntPtr i) => -i; static nint F2(nint i) => -i; }"; var comp = CreateEmptyCompilation(new[] { sourceA, sourceB }, parseOptions: TestOptions.Regular9); comp.VerifyDiagnostics(); var verifier = CompileAndVerify(comp, emitOptions: EmitOptions.Default.WithRuntimeMetadataVersion("0.0.0.0"), verify: Verification.Skipped); verifier.VerifyIL("Program.F1", @"{ // Code size 7 (0x7) .maxstack 1 IL_0000: ldarg.0 IL_0001: call ""System.IntPtr System.IntPtr.op_UnaryNegation(System.IntPtr)"" IL_0006: ret }"); verifier.VerifyIL("Program.F2", @"{ // Code size 3 (0x3) .maxstack 1 IL_0000: ldarg.0 IL_0001: neg IL_0002: ret }"); } [Fact] public void UnaryAndBinaryOperators_UserDefinedConversions() { verifyBoth("System.IntPtr", // (5,9): error CS0266: Cannot implicitly convert type 'long' to 'MyInt'. An explicit conversion exists (are you missing a cast?) // ++x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "++x").WithArguments("long", "MyInt").WithLocation(5, 9), // (6,9): error CS0266: Cannot implicitly convert type 'long' to 'MyInt'. An explicit conversion exists (are you missing a cast?) // x++; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x++").WithArguments("long", "MyInt").WithLocation(6, 9), // (7,9): error CS0266: Cannot implicitly convert type 'long' to 'MyInt'. An explicit conversion exists (are you missing a cast?) // --x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "--x").WithArguments("long", "MyInt").WithLocation(7, 9), // (8,9): error CS0266: Cannot implicitly convert type 'long' to 'MyInt'. An explicit conversion exists (are you missing a cast?) // x--; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x--").WithArguments("long", "MyInt").WithLocation(8, 9) ); verifyBoth("System.IntPtr?", // (5,9): error CS0266: Cannot implicitly convert type 'long?' to 'MyInt'. An explicit conversion exists (are you missing a cast?) // ++x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "++x").WithArguments("long?", "MyInt").WithLocation(5, 9), // (6,9): error CS0266: Cannot implicitly convert type 'long?' to 'MyInt'. An explicit conversion exists (are you missing a cast?) // x++; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x++").WithArguments("long?", "MyInt").WithLocation(6, 9), // (7,9): error CS0266: Cannot implicitly convert type 'long?' to 'MyInt'. An explicit conversion exists (are you missing a cast?) // --x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "--x").WithArguments("long?", "MyInt").WithLocation(7, 9), // (8,9): error CS0266: Cannot implicitly convert type 'long?' to 'MyInt'. An explicit conversion exists (are you missing a cast?) // x--; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x--").WithArguments("long?", "MyInt").WithLocation(8, 9) ); verifyBoth("System.UIntPtr", // (5,9): error CS0266: Cannot implicitly convert type 'ulong' to 'MyInt'. An explicit conversion exists (are you missing a cast?) // ++x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "++x").WithArguments("ulong", "MyInt").WithLocation(5, 9), // (6,9): error CS0266: Cannot implicitly convert type 'ulong' to 'MyInt'. An explicit conversion exists (are you missing a cast?) // x++; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x++").WithArguments("ulong", "MyInt").WithLocation(6, 9), // (7,9): error CS0266: Cannot implicitly convert type 'ulong' to 'MyInt'. An explicit conversion exists (are you missing a cast?) // --x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "--x").WithArguments("ulong", "MyInt").WithLocation(7, 9), // (8,9): error CS0266: Cannot implicitly convert type 'ulong' to 'MyInt'. An explicit conversion exists (are you missing a cast?) // x--; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x--").WithArguments("ulong", "MyInt").WithLocation(8, 9), // (10,13): error CS0035: Operator '-' is ambiguous on an operand of type 'MyInt' // _ = -x; Diagnostic(ErrorCode.ERR_AmbigUnaryOp, "-x").WithArguments("-", "MyInt").WithLocation(10, 13) ); verifyBoth("System.UIntPtr?", // (5,9): error CS0266: Cannot implicitly convert type 'ulong?' to 'MyInt'. An explicit conversion exists (are you missing a cast?) // ++x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "++x").WithArguments("ulong?", "MyInt").WithLocation(5, 9), // (6,9): error CS0266: Cannot implicitly convert type 'ulong?' to 'MyInt'. An explicit conversion exists (are you missing a cast?) // x++; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x++").WithArguments("ulong?", "MyInt").WithLocation(6, 9), // (7,9): error CS0266: Cannot implicitly convert type 'ulong?' to 'MyInt'. An explicit conversion exists (are you missing a cast?) // --x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "--x").WithArguments("ulong?", "MyInt").WithLocation(7, 9), // (8,9): error CS0266: Cannot implicitly convert type 'ulong?' to 'MyInt'. An explicit conversion exists (are you missing a cast?) // x--; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x--").WithArguments("ulong?", "MyInt").WithLocation(8, 9), // (10,13): error CS0035: Operator '-' is ambiguous on an operand of type 'MyInt' // _ = -x; Diagnostic(ErrorCode.ERR_AmbigUnaryOp, "-x").WithArguments("-", "MyInt").WithLocation(10, 13) ); void verifyBoth(string type, params DiagnosticDescription[] expected) { verify(type, expected); verify(AsNative(type), expected); } void verify(string type, params DiagnosticDescription[] expected) { string sourceA = $@"class MyInt {{ public static implicit operator {type}(MyInt i) => throw null; public static implicit operator MyInt({type} i) => throw null; }}"; string sourceB = @"class Program { static void F(MyInt x, MyInt y) { ++x; x++; --x; x--; _ = +x; _ = -x; _ = ~x; _ = x + y; _ = x * y; _ = x < y; _ = x & y; _ = x << 1; } }"; var comp = CreateCompilation(new[] { sourceA, sourceB }, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(expected); } } [Fact] public void BinaryOperators() { void unifiedBinaryOps(string op, string leftType, string rightType, string expectedSymbol1 = null, string expectedSymbol2 = "", DiagnosticDescription[] diagnostics1 = null, DiagnosticDescription[] diagnostics2 = null) { binaryOps(op, leftType, rightType, expectedSymbol1, expectedSymbol2, diagnostics1, diagnostics2); var fullLeftType = leftType switch { "nint" => "System.IntPtr", "nint?" => "System.IntPtr?", "nuint" => "System.UIntPtr", "nuint?" => "System.UIntPtr?", _ => throw ExceptionUtilities.Unreachable() }; binaryOps(op, fullLeftType, rightType, expectedSymbol1, expectedSymbol2, diagnostics1, diagnostics2); } void binaryOps(string op, string leftType, string rightType, string expectedSymbol1 = null, string expectedSymbol2 = "", DiagnosticDescription[] diagnostics1 = null, DiagnosticDescription[] diagnostics2 = null) { binaryOp(op, leftType, rightType, expectedSymbol1, diagnostics1); binaryOp(op, rightType, leftType, expectedSymbol2 == "" ? expectedSymbol1 : expectedSymbol2, diagnostics2 ?? diagnostics1); } void binaryOp(string op, string leftType, string rightType, string expectedSymbol, DiagnosticDescription[] diagnostics) { if (expectedSymbol == null && diagnostics == null) { diagnostics = getBadBinaryOpsDiagnostics(op, leftType, rightType); } binaryOperator(op, leftType, rightType, expectedSymbol, diagnostics ?? Array.Empty<DiagnosticDescription>()); } static DiagnosticDescription[] getBadBinaryOpsDiagnostics(string op, string leftType, string rightType, bool includeBadBinaryOps = true, bool includeVoidError = false) { var builder = ArrayBuilder<DiagnosticDescription>.GetInstance(); if (includeBadBinaryOps) builder.Add(Diagnostic(ErrorCode.ERR_BadBinaryOps, $"x {op} y").WithArguments(op, AsNative(leftType), AsNative(rightType))); if (includeVoidError) builder.Add(Diagnostic(ErrorCode.ERR_VoidError, $"x {op} y")); return builder.ToArrayAndFree(); } static DiagnosticDescription[] getAmbiguousBinaryOpsDiagnostics(string op, string leftType, string rightType) { return new[] { Diagnostic(ErrorCode.ERR_AmbigBinaryOps, $"x {op} y").WithArguments(op, leftType, rightType) }; } var arithmeticOperators = new[] { ("-", "op_Subtraction"), ("*", "op_Multiply"), ("/", "op_Division"), ("%", "op_Modulus"), }; var additionOperators = new[] { ("+", "op_Addition"), }; var comparisonOperators = new[] { ("<", "op_LessThan"), ("<=", "op_LessThanOrEqual"), (">", "op_GreaterThan"), (">=", "op_GreaterThanOrEqual"), }; var shiftOperators = new[] { ("<<", "op_LeftShift"), (">>", "op_RightShift"), }; var equalityOperators = new[] { ("==", "op_Equality"), ("!=", "op_Inequality"), }; var logicalOperators = new[] { ("&", "op_BitwiseAnd"), ("|", "op_BitwiseOr"), ("^", "op_ExclusiveOr"), }; foreach ((string symbol, string name) in arithmeticOperators) { bool includeBadBinaryOps = (symbol != "-"); // nint arithmeticOp type unifiedBinaryOps(symbol, "nint", "object"); unifiedBinaryOps(symbol, "nint", "string"); unifiedBinaryOps(symbol, "nint", "void*", null, (symbol == "-") ? $"void* void*.{name}(void* left, long right)" : null, getBadBinaryOpsDiagnostics(symbol, "nint", "void*", includeVoidError: true), getBadBinaryOpsDiagnostics(symbol, "void*", "nint", includeBadBinaryOps: includeBadBinaryOps, includeVoidError: true)); unifiedBinaryOps(symbol, "nint", "bool"); unifiedBinaryOps(symbol, "nint", "char", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "sbyte", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "byte", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "short", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "ushort", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "int", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "uint", $"long long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint", "nint", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "nuint", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint")); unifiedBinaryOps(symbol, "nint", "long", $"long long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint", "ulong", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "ulong"), getAmbiguousBinaryOpsDiagnostics(symbol, "ulong", "nint")); unifiedBinaryOps(symbol, "nint", "float", $"float float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nint", "double", $"double double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nint", "decimal", $"decimal decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nint", "System.IntPtr", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "System.UIntPtr", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint")); // nint arithmeticOp type? unifiedBinaryOps(symbol, "nint", "bool?"); unifiedBinaryOps(symbol, "nint", "char?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "sbyte?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "byte?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "short?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "ushort?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "int?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "uint?", $"long long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint", "nint?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "nuint?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint")); unifiedBinaryOps(symbol, "nint", "long?", $"long long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint", "ulong?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "ulong?"), getAmbiguousBinaryOpsDiagnostics(symbol, "ulong?", "nint")); unifiedBinaryOps(symbol, "nint", "float?", $"float float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nint", "double?", $"double double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nint", "decimal?", $"decimal decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nint", "System.IntPtr?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "System.UIntPtr?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint")); unifiedBinaryOps(symbol, "nint", "object"); // nint? arithmeticOp type unifiedBinaryOps(symbol, "nint?", "string"); unifiedBinaryOps(symbol, "nint?", "void*", null, null, getBadBinaryOpsDiagnostics(symbol, "nint?", "void*", includeVoidError: true), getBadBinaryOpsDiagnostics(symbol, "void*", "nint?", includeVoidError: true)); unifiedBinaryOps(symbol, "nint?", "bool"); unifiedBinaryOps(symbol, "nint?", "char", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "sbyte", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "byte", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "short", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "ushort", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "int", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "uint", $"long long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint?", "nint", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "nuint", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint?")); unifiedBinaryOps(symbol, "nint?", "long", $"long long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint?", "ulong", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "ulong"), getAmbiguousBinaryOpsDiagnostics(symbol, "ulong", "nint?")); unifiedBinaryOps(symbol, "nint?", "float", $"float float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nint?", "double", $"double double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nint?", "decimal", $"decimal decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nint?", "System.IntPtr", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "System.UIntPtr", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint?")); // nint? arithmeticOp type? unifiedBinaryOps(symbol, "nint?", "bool?"); unifiedBinaryOps(symbol, "nint?", "char?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "sbyte?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "byte?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "short?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "ushort?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "int?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "uint?", $"long long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint?", "nint?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "nuint?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint?")); unifiedBinaryOps(symbol, "nint?", "long?", $"long long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint?", "ulong?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "ulong?"), getAmbiguousBinaryOpsDiagnostics(symbol, "ulong?", "nint?")); unifiedBinaryOps(symbol, "nint?", "float?", $"float float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nint?", "double?", $"double double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nint?", "decimal?", $"decimal decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nint?", "System.IntPtr?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "System.UIntPtr?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint?")); // nuint arithmeticOp type unifiedBinaryOps(symbol, "nuint", "object"); unifiedBinaryOps(symbol, "nuint", "string"); unifiedBinaryOps(symbol, "nuint", "void*", null, (symbol == "-") ? $"void* void*.{name}(void* left, ulong right)" : null, getBadBinaryOpsDiagnostics(symbol, "nuint", "void*", includeVoidError: true), getBadBinaryOpsDiagnostics(symbol, "void*", "nuint", includeBadBinaryOps: includeBadBinaryOps, includeVoidError: true)); unifiedBinaryOps(symbol, "nuint", "bool"); unifiedBinaryOps(symbol, "nuint", "char", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "sbyte", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "sbyte"), getAmbiguousBinaryOpsDiagnostics(symbol, "sbyte", "nuint")); unifiedBinaryOps(symbol, "nuint", "byte", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "short", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "short"), getAmbiguousBinaryOpsDiagnostics(symbol, "short", "nuint")); unifiedBinaryOps(symbol, "nuint", "ushort", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "int", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "int"), getAmbiguousBinaryOpsDiagnostics(symbol, "int", "nuint")); unifiedBinaryOps(symbol, "nuint", "uint", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "nint", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint")); unifiedBinaryOps(symbol, "nuint", "nuint", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "long", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "long"), getAmbiguousBinaryOpsDiagnostics(symbol, "long", "nuint")); unifiedBinaryOps(symbol, "nuint", "ulong", $"ulong ulong.{name}(ulong left, ulong right)"); unifiedBinaryOps(symbol, "nuint", "float", $"float float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nuint", "double", $"double double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nuint", "decimal", $"decimal decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nuint", "System.IntPtr", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint")); unifiedBinaryOps(symbol, "nuint", "System.UIntPtr", $"nuint nuint.{name}(nuint left, nuint right)"); // nuint arithmeticOp type? unifiedBinaryOps(symbol, "nuint", "bool?"); unifiedBinaryOps(symbol, "nuint", "char?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "sbyte?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "sbyte?"), getAmbiguousBinaryOpsDiagnostics(symbol, "sbyte?", "nuint")); unifiedBinaryOps(symbol, "nuint", "byte?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "short?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "short?"), getAmbiguousBinaryOpsDiagnostics(symbol, "short?", "nuint")); unifiedBinaryOps(symbol, "nuint", "ushort?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "int?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "int?"), getAmbiguousBinaryOpsDiagnostics(symbol, "int?", "nuint")); unifiedBinaryOps(symbol, "nuint", "uint?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "nint?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint")); unifiedBinaryOps(symbol, "nuint", "nuint?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "long?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "long?"), getAmbiguousBinaryOpsDiagnostics(symbol, "long?", "nuint")); unifiedBinaryOps(symbol, "nuint", "ulong?", $"ulong ulong.{name}(ulong left, ulong right)"); unifiedBinaryOps(symbol, "nuint", "float?", $"float float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nuint", "double?", $"double double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nuint", "decimal?", $"decimal decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nuint", "System.IntPtr?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint")); unifiedBinaryOps(symbol, "nuint", "System.UIntPtr?", $"nuint nuint.{name}(nuint left, nuint right)"); // nuint? arithmeticOp type unifiedBinaryOps(symbol, "nuint?", "object"); unifiedBinaryOps(symbol, "nuint?", "string"); unifiedBinaryOps(symbol, "nuint?", "void*", null, null, getBadBinaryOpsDiagnostics(symbol, "nuint?", "void*", includeVoidError: true), getBadBinaryOpsDiagnostics(symbol, "void*", "nuint?", includeVoidError: true)); unifiedBinaryOps(symbol, "nuint?", "bool"); unifiedBinaryOps(symbol, "nuint?", "char", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "sbyte", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "sbyte"), getAmbiguousBinaryOpsDiagnostics(symbol, "sbyte", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "byte", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "short", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "short"), getAmbiguousBinaryOpsDiagnostics(symbol, "short", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "ushort", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "int", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "int"), getAmbiguousBinaryOpsDiagnostics(symbol, "int", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "uint", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "nint", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "nuint", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "long", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "long"), getAmbiguousBinaryOpsDiagnostics(symbol, "long", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "ulong", $"ulong ulong.{name}(ulong left, ulong right)"); unifiedBinaryOps(symbol, "nuint?", "float", $"float float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nuint?", "double", $"double double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nuint?", "decimal", $"decimal decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nuint?", "System.IntPtr", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "System.UIntPtr", $"nuint nuint.{name}(nuint left, nuint right)"); // nuint? arithmeticOp type? unifiedBinaryOps(symbol, "nuint?", "bool?"); unifiedBinaryOps(symbol, "nuint?", "char?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "sbyte?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "sbyte?"), getAmbiguousBinaryOpsDiagnostics(symbol, "sbyte?", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "byte?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "short?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "short?"), getAmbiguousBinaryOpsDiagnostics(symbol, "short?", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "ushort?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "int?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "int?"), getAmbiguousBinaryOpsDiagnostics(symbol, "int?", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "uint?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "nint?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "nuint?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "long?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "long?"), getAmbiguousBinaryOpsDiagnostics(symbol, "long?", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "ulong?", $"ulong ulong.{name}(ulong left, ulong right)"); unifiedBinaryOps(symbol, "nuint?", "float?", $"float float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nuint?", "double?", $"double double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nuint?", "decimal?", $"decimal decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nuint?", "System.IntPtr?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "System.UIntPtr?", $"nuint nuint.{name}(nuint left, nuint right)"); } foreach ((string symbol, string name) in comparisonOperators) { // nint comparisonOp type unifiedBinaryOps(symbol, "nint", "object"); unifiedBinaryOps(symbol, "nint", "string"); unifiedBinaryOps(symbol, "nint", "void*", null, null, getBadBinaryOpsDiagnostics(symbol, "nint", "void*"), getBadBinaryOpsDiagnostics(symbol, "void*", "nint")); unifiedBinaryOps(symbol, "nint", "bool"); unifiedBinaryOps(symbol, "nint", "char", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "sbyte", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "byte", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "short", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "ushort", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "int", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "uint", $"bool long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint", "nint", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "nuint", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint")); unifiedBinaryOps(symbol, "nint", "long", $"bool long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint", "ulong", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "ulong"), getAmbiguousBinaryOpsDiagnostics(symbol, "ulong", "nint")); unifiedBinaryOps(symbol, "nint", "float", $"bool float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nint", "double", $"bool double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nint", "decimal", $"bool decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nint", "System.IntPtr", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "System.UIntPtr", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint")); // nint comparisonOp type? unifiedBinaryOps(symbol, "nint", "bool?"); unifiedBinaryOps(symbol, "nint", "char?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "sbyte?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "byte?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "short?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "ushort?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "int?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "uint?", $"bool long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint", "nint?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "nuint?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint")); unifiedBinaryOps(symbol, "nint", "long?", $"bool long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint", "ulong?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "ulong?"), getAmbiguousBinaryOpsDiagnostics(symbol, "ulong?", "nint")); unifiedBinaryOps(symbol, "nint", "float?", $"bool float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nint", "double?", $"bool double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nint", "decimal?", $"bool decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nint", "System.IntPtr?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "System.UIntPtr?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint")); unifiedBinaryOps(symbol, "nint", "object"); // nint? comparisonOp type unifiedBinaryOps(symbol, "nint?", "string"); unifiedBinaryOps(symbol, "nint?", "void*", null, null, getBadBinaryOpsDiagnostics(symbol, "nint?", "void*"), getBadBinaryOpsDiagnostics(symbol, "void*", "nint?")); unifiedBinaryOps(symbol, "nint?", "bool"); unifiedBinaryOps(symbol, "nint?", "char", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "sbyte", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "byte", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "short", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "ushort", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "int", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "uint", $"bool long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint?", "nint", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "nuint", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint?")); unifiedBinaryOps(symbol, "nint?", "long", $"bool long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint?", "ulong", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "ulong"), getAmbiguousBinaryOpsDiagnostics(symbol, "ulong", "nint?")); unifiedBinaryOps(symbol, "nint?", "float", $"bool float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nint?", "double", $"bool double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nint?", "decimal", $"bool decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nint?", "System.IntPtr", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "System.UIntPtr", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint?")); // nint? comparisonOp type? unifiedBinaryOps(symbol, "nint?", "bool?"); unifiedBinaryOps(symbol, "nint?", "char?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "sbyte?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "byte?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "short?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "ushort?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "int?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "uint?", $"bool long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint?", "nint?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "nuint?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint?")); unifiedBinaryOps(symbol, "nint?", "long?", $"bool long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint?", "ulong?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "ulong?"), getAmbiguousBinaryOpsDiagnostics(symbol, "ulong?", "nint?")); unifiedBinaryOps(symbol, "nint?", "float?", $"bool float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nint?", "double?", $"bool double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nint?", "decimal?", $"bool decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nint?", "System.IntPtr?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "System.UIntPtr?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint?")); // nuint comparisonOp type unifiedBinaryOps(symbol, "nuint", "object"); unifiedBinaryOps(symbol, "nuint", "string"); unifiedBinaryOps(symbol, "nuint", "void*", null, null, getBadBinaryOpsDiagnostics(symbol, "nuint", "void*"), getBadBinaryOpsDiagnostics(symbol, "void*", "nuint")); unifiedBinaryOps(symbol, "nuint", "bool"); unifiedBinaryOps(symbol, "nuint", "char", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "sbyte", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "sbyte"), getAmbiguousBinaryOpsDiagnostics(symbol, "sbyte", "nuint")); unifiedBinaryOps(symbol, "nuint", "byte", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "short", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "short"), getAmbiguousBinaryOpsDiagnostics(symbol, "short", "nuint")); unifiedBinaryOps(symbol, "nuint", "ushort", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "int", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "int"), getAmbiguousBinaryOpsDiagnostics(symbol, "int", "nuint")); unifiedBinaryOps(symbol, "nuint", "uint", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "nint", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint")); unifiedBinaryOps(symbol, "nuint", "nuint", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "long", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "long"), getAmbiguousBinaryOpsDiagnostics(symbol, "long", "nuint")); unifiedBinaryOps(symbol, "nuint", "ulong", $"bool ulong.{name}(ulong left, ulong right)"); unifiedBinaryOps(symbol, "nuint", "float", $"bool float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nuint", "double", $"bool double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nuint", "decimal", $"bool decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nuint", "System.IntPtr", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint")); unifiedBinaryOps(symbol, "nuint", "System.UIntPtr", $"bool nuint.{name}(nuint left, nuint right)"); // nuint comparisonOp type? unifiedBinaryOps(symbol, "nuint", "bool?"); unifiedBinaryOps(symbol, "nuint", "char?", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "sbyte?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "sbyte?"), getAmbiguousBinaryOpsDiagnostics(symbol, "sbyte?", "nuint")); unifiedBinaryOps(symbol, "nuint", "byte?", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "short?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "short?"), getAmbiguousBinaryOpsDiagnostics(symbol, "short?", "nuint")); unifiedBinaryOps(symbol, "nuint", "ushort?", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "int?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "int?"), getAmbiguousBinaryOpsDiagnostics(symbol, "int?", "nuint")); unifiedBinaryOps(symbol, "nuint", "uint?", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "nint?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint")); unifiedBinaryOps(symbol, "nuint", "nuint?", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "long?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "long?"), getAmbiguousBinaryOpsDiagnostics(symbol, "long?", "nuint")); unifiedBinaryOps(symbol, "nuint", "ulong?", $"bool ulong.{name}(ulong left, ulong right)"); unifiedBinaryOps(symbol, "nuint", "float?", $"bool float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nuint", "double?", $"bool double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nuint", "decimal?", $"bool decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nuint", "System.IntPtr?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint")); unifiedBinaryOps(symbol, "nuint", "System.UIntPtr?", $"bool nuint.{name}(nuint left, nuint right)"); // nuint? comparisonOp type unifiedBinaryOps(symbol, "nuint?", "object"); unifiedBinaryOps(symbol, "nuint?", "string"); unifiedBinaryOps(symbol, "nuint?", "void*", null, null, getBadBinaryOpsDiagnostics(symbol, "nuint?", "void*"), getBadBinaryOpsDiagnostics(symbol, "void*", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "bool"); unifiedBinaryOps(symbol, "nuint?", "char", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "sbyte", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "sbyte"), getAmbiguousBinaryOpsDiagnostics(symbol, "sbyte", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "byte", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "short", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "short"), getAmbiguousBinaryOpsDiagnostics(symbol, "short", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "ushort", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "int", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "int"), getAmbiguousBinaryOpsDiagnostics(symbol, "int", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "uint", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "nint", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "nuint", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "long", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "long"), getAmbiguousBinaryOpsDiagnostics(symbol, "long", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "ulong", $"bool ulong.{name}(ulong left, ulong right)"); unifiedBinaryOps(symbol, "nuint?", "float", $"bool float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nuint?", "double", $"bool double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nuint?", "decimal", $"bool decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nuint?", "System.IntPtr", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "System.UIntPtr", $"bool nuint.{name}(nuint left, nuint right)"); // nuint comparisonOp type? unifiedBinaryOps(symbol, "nuint?", "bool?"); unifiedBinaryOps(symbol, "nuint?", "char?", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "sbyte?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "sbyte?"), getAmbiguousBinaryOpsDiagnostics(symbol, "sbyte?", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "byte?", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "short?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "short?"), getAmbiguousBinaryOpsDiagnostics(symbol, "short?", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "ushort?", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "int?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "int?"), getAmbiguousBinaryOpsDiagnostics(symbol, "int?", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "uint?", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "nint?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "nuint?", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "long?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "long?"), getAmbiguousBinaryOpsDiagnostics(symbol, "long?", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "ulong?", $"bool ulong.{name}(ulong left, ulong right)"); unifiedBinaryOps(symbol, "nuint?", "float?", $"bool float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nuint?", "double?", $"bool double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nuint?", "decimal?", $"bool decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nuint?", "System.IntPtr?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "System.UIntPtr?", $"bool nuint.{name}(nuint left, nuint right)"); } foreach ((string symbol, string name) in additionOperators) { // nint additionOperator type unifiedBinaryOps(symbol, "nint", "object"); unifiedBinaryOps(symbol, "nint", "string", $"string string.{name}(object left, string right)", $"string string.{name}(string left, object right)"); unifiedBinaryOps(symbol, "nint", "void*", $"void* void*.{name}(long left, void* right)", $"void* void*.{name}(void* left, long right)", new[] { Diagnostic(ErrorCode.ERR_VoidError, "x + y") }); unifiedBinaryOps(symbol, "nint", "bool"); unifiedBinaryOps(symbol, "nint", "char", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "sbyte", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "byte", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "short", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "ushort", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "int", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "uint", $"long long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint", "nint", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "nuint", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint")); unifiedBinaryOps(symbol, "nint", "long", $"long long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint", "ulong", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "ulong"), getAmbiguousBinaryOpsDiagnostics(symbol, "ulong", "nint")); unifiedBinaryOps(symbol, "nint", "float", $"float float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nint", "double", $"double double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nint", "decimal", $"decimal decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nint", "System.IntPtr", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "System.UIntPtr", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint")); // nint additionOperator type? unifiedBinaryOps(symbol, "nint", "bool?"); unifiedBinaryOps(symbol, "nint", "char?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "sbyte?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "byte?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "short?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "ushort?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "int?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "uint?", $"long long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint", "nint?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "nuint?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint")); unifiedBinaryOps(symbol, "nint", "long?", $"long long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint", "ulong?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "ulong?"), getAmbiguousBinaryOpsDiagnostics(symbol, "ulong?", "nint")); unifiedBinaryOps(symbol, "nint", "float?", $"float float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nint", "double?", $"double double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nint", "decimal?", $"decimal decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nint", "System.IntPtr?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "System.UIntPtr?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint")); unifiedBinaryOps(symbol, "nint", "object"); // nint? additionOperator type unifiedBinaryOps(symbol, "nint?", "string", $"string string.{name}(object left, string right)", $"string string.{name}(string left, object right)"); unifiedBinaryOps(symbol, "nint?", "void*", null, null, getBadBinaryOpsDiagnostics(symbol, "nint?", "void*", includeVoidError: true), getBadBinaryOpsDiagnostics(symbol, "void*", "nint?", includeVoidError: true)); unifiedBinaryOps(symbol, "nint?", "bool"); unifiedBinaryOps(symbol, "nint?", "char", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "sbyte", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "byte", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "short", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "ushort", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "int", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "uint", $"long long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint?", "nint", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "nuint", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint?")); unifiedBinaryOps(symbol, "nint?", "long", $"long long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint?", "ulong", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "ulong"), getAmbiguousBinaryOpsDiagnostics(symbol, "ulong", "nint?")); unifiedBinaryOps(symbol, "nint?", "float", $"float float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nint?", "double", $"double double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nint?", "decimal", $"decimal decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nint?", "System.IntPtr", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "System.UIntPtr", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint?")); // nint? additionOperator type? unifiedBinaryOps(symbol, "nint?", "bool?"); unifiedBinaryOps(symbol, "nint?", "char?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "sbyte?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "byte?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "short?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "ushort?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "int?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "uint?", $"long long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint?", "nint?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "nuint?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint?")); unifiedBinaryOps(symbol, "nint?", "long?", $"long long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint?", "ulong?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "ulong?"), getAmbiguousBinaryOpsDiagnostics(symbol, "ulong?", "nint?")); unifiedBinaryOps(symbol, "nint?", "float?", $"float float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nint?", "double?", $"double double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nint?", "decimal?", $"decimal decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nint?", "System.IntPtr?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "System.UIntPtr?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint?")); // nuint additionOperator type unifiedBinaryOps(symbol, "nuint", "object"); unifiedBinaryOps(symbol, "nuint", "string", $"string string.{name}(object left, string right)", $"string string.{name}(string left, object right)"); unifiedBinaryOps(symbol, "nuint", "void*", $"void* void*.{name}(ulong left, void* right)", $"void* void*.{name}(void* left, ulong right)", new[] { Diagnostic(ErrorCode.ERR_VoidError, "x + y") }); unifiedBinaryOps(symbol, "nuint", "bool"); unifiedBinaryOps(symbol, "nuint", "char", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "sbyte", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "sbyte"), getAmbiguousBinaryOpsDiagnostics(symbol, "sbyte", "nuint")); unifiedBinaryOps(symbol, "nuint", "byte", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "short", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "short"), getAmbiguousBinaryOpsDiagnostics(symbol, "short", "nuint")); unifiedBinaryOps(symbol, "nuint", "ushort", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "int", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "int"), getAmbiguousBinaryOpsDiagnostics(symbol, "int", "nuint")); unifiedBinaryOps(symbol, "nuint", "uint", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "nint", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint")); unifiedBinaryOps(symbol, "nuint", "nuint", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "long", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "long"), getAmbiguousBinaryOpsDiagnostics(symbol, "long", "nuint")); unifiedBinaryOps(symbol, "nuint", "ulong", $"ulong ulong.{name}(ulong left, ulong right)"); unifiedBinaryOps(symbol, "nuint", "float", $"float float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nuint", "double", $"double double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nuint", "decimal", $"decimal decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nuint", "System.IntPtr", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint")); unifiedBinaryOps(symbol, "nuint", "System.UIntPtr", $"nuint nuint.{name}(nuint left, nuint right)"); // nuint additionOperator type? unifiedBinaryOps(symbol, "nuint", "bool?"); unifiedBinaryOps(symbol, "nuint", "char?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "sbyte?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "sbyte?"), getAmbiguousBinaryOpsDiagnostics(symbol, "sbyte?", "nuint")); unifiedBinaryOps(symbol, "nuint", "byte?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "short?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "short?"), getAmbiguousBinaryOpsDiagnostics(symbol, "short?", "nuint")); unifiedBinaryOps(symbol, "nuint", "ushort?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "int?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "int?"), getAmbiguousBinaryOpsDiagnostics(symbol, "int?", "nuint")); unifiedBinaryOps(symbol, "nuint", "uint?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "nint?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint")); unifiedBinaryOps(symbol, "nuint", "nuint?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "long?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "long?"), getAmbiguousBinaryOpsDiagnostics(symbol, "long?", "nuint")); unifiedBinaryOps(symbol, "nuint", "ulong?", $"ulong ulong.{name}(ulong left, ulong right)"); unifiedBinaryOps(symbol, "nuint", "float?", $"float float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nuint", "double?", $"double double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nuint", "decimal?", $"decimal decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nuint", "System.IntPtr?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint")); unifiedBinaryOps(symbol, "nuint", "System.UIntPtr?", $"nuint nuint.{name}(nuint left, nuint right)"); // nuint? additionOperator type unifiedBinaryOps(symbol, "nuint?", "object"); unifiedBinaryOps(symbol, "nuint?", "string", $"string string.{name}(object left, string right)", $"string string.{name}(string left, object right)"); unifiedBinaryOps(symbol, "nuint?", "void*", null, null, getBadBinaryOpsDiagnostics(symbol, "nuint?", "void*", includeVoidError: true), getBadBinaryOpsDiagnostics(symbol, "void*", "nuint?", includeVoidError: true)); unifiedBinaryOps(symbol, "nuint?", "bool"); unifiedBinaryOps(symbol, "nuint?", "char", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "sbyte", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "sbyte"), getAmbiguousBinaryOpsDiagnostics(symbol, "sbyte", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "byte", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "short", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "short"), getAmbiguousBinaryOpsDiagnostics(symbol, "short", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "ushort", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "int", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "int"), getAmbiguousBinaryOpsDiagnostics(symbol, "int", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "uint", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "nint", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "nuint", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "long", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "long"), getAmbiguousBinaryOpsDiagnostics(symbol, "long", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "ulong", $"ulong ulong.{name}(ulong left, ulong right)"); unifiedBinaryOps(symbol, "nuint?", "float", $"float float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nuint?", "double", $"double double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nuint?", "decimal", $"decimal decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nuint?", "System.IntPtr", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "System.UIntPtr", $"nuint nuint.{name}(nuint left, nuint right)"); // nuint? additionOperator type? unifiedBinaryOps(symbol, "nuint?", "bool?"); unifiedBinaryOps(symbol, "nuint?", "char?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "sbyte?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "sbyte?"), getAmbiguousBinaryOpsDiagnostics(symbol, "sbyte?", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "byte?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "short?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "short?"), getAmbiguousBinaryOpsDiagnostics(symbol, "short?", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "ushort?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "int?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "int?"), getAmbiguousBinaryOpsDiagnostics(symbol, "int?", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "uint?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "nint?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "nuint?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "long?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "long?"), getAmbiguousBinaryOpsDiagnostics(symbol, "long?", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "ulong?", $"ulong ulong.{name}(ulong left, ulong right)"); unifiedBinaryOps(symbol, "nuint?", "float?", $"float float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nuint?", "double?", $"double double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nuint?", "decimal?", $"decimal decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nuint?", "System.IntPtr?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "System.UIntPtr?", $"nuint nuint.{name}(nuint left, nuint right)"); } foreach ((string symbol, string name) in shiftOperators) { // nint shiftOp type unifiedBinaryOps(symbol, "nint", "object"); unifiedBinaryOps(symbol, "nint", "string"); unifiedBinaryOps(symbol, "nint", "void*", null, null, getBadBinaryOpsDiagnostics(symbol, "nint", "void*", includeVoidError: true), getBadBinaryOpsDiagnostics(symbol, "void*", "nint", includeVoidError: true)); unifiedBinaryOps(symbol, "nint", "bool"); unifiedBinaryOps(symbol, "nint", "char", $"nint nint.{name}(nint left, int right)", null); unifiedBinaryOps(symbol, "nint", "sbyte", $"nint nint.{name}(nint left, int right)", null); unifiedBinaryOps(symbol, "nint", "byte", $"nint nint.{name}(nint left, int right)", null); unifiedBinaryOps(symbol, "nint", "short", $"nint nint.{name}(nint left, int right)", null); unifiedBinaryOps(symbol, "nint", "ushort", $"nint nint.{name}(nint left, int right)", null); unifiedBinaryOps(symbol, "nint", "int", $"nint nint.{name}(nint left, int right)", null); unifiedBinaryOps(symbol, "nint", "uint"); unifiedBinaryOps(symbol, "nint", "nint"); unifiedBinaryOps(symbol, "nint", "nuint"); unifiedBinaryOps(symbol, "nint", "long"); unifiedBinaryOps(symbol, "nint", "ulong"); unifiedBinaryOps(symbol, "nint", "float"); unifiedBinaryOps(symbol, "nint", "double"); unifiedBinaryOps(symbol, "nint", "decimal"); unifiedBinaryOps(symbol, "nint", "System.IntPtr"); unifiedBinaryOps(symbol, "nint", "System.UIntPtr"); // nint shiftOp type? unifiedBinaryOps(symbol, "nint", "bool?"); unifiedBinaryOps(symbol, "nint", "char?", $"nint nint.{name}(nint left, int right)", null); unifiedBinaryOps(symbol, "nint", "sbyte?", $"nint nint.{name}(nint left, int right)", null); unifiedBinaryOps(symbol, "nint", "byte?", $"nint nint.{name}(nint left, int right)", null); unifiedBinaryOps(symbol, "nint", "short?", $"nint nint.{name}(nint left, int right)", null); unifiedBinaryOps(symbol, "nint", "ushort?", $"nint nint.{name}(nint left, int right)", null); unifiedBinaryOps(symbol, "nint", "int?", $"nint nint.{name}(nint left, int right)", null); unifiedBinaryOps(symbol, "nint", "uint?"); unifiedBinaryOps(symbol, "nint", "nint?"); unifiedBinaryOps(symbol, "nint", "nuint?"); unifiedBinaryOps(symbol, "nint", "long?"); unifiedBinaryOps(symbol, "nint", "ulong?"); unifiedBinaryOps(symbol, "nint", "float?"); unifiedBinaryOps(symbol, "nint", "double?"); unifiedBinaryOps(symbol, "nint", "decimal?"); unifiedBinaryOps(symbol, "nint", "System.IntPtr?"); unifiedBinaryOps(symbol, "nint", "System.UIntPtr?"); unifiedBinaryOps(symbol, "nint", "object"); // nint? shiftOp type unifiedBinaryOps(symbol, "nint?", "string"); unifiedBinaryOps(symbol, "nint?", "void*", null, null, getBadBinaryOpsDiagnostics(symbol, "nint?", "void*", includeVoidError: true), getBadBinaryOpsDiagnostics(symbol, "void*", "nint?", includeVoidError: true)); unifiedBinaryOps(symbol, "nint?", "bool"); unifiedBinaryOps(symbol, "nint?", "char", $"nint nint.{name}(nint left, int right)", null); unifiedBinaryOps(symbol, "nint?", "sbyte", $"nint nint.{name}(nint left, int right)", null); unifiedBinaryOps(symbol, "nint?", "byte", $"nint nint.{name}(nint left, int right)", null); unifiedBinaryOps(symbol, "nint?", "short", $"nint nint.{name}(nint left, int right)", null); unifiedBinaryOps(symbol, "nint?", "ushort", $"nint nint.{name}(nint left, int right)", null); unifiedBinaryOps(symbol, "nint?", "int", $"nint nint.{name}(nint left, int right)", null); unifiedBinaryOps(symbol, "nint?", "uint"); unifiedBinaryOps(symbol, "nint?", "nint"); unifiedBinaryOps(symbol, "nint?", "nuint"); unifiedBinaryOps(symbol, "nint?", "long"); unifiedBinaryOps(symbol, "nint?", "ulong"); unifiedBinaryOps(symbol, "nint?", "float"); unifiedBinaryOps(symbol, "nint?", "double"); unifiedBinaryOps(symbol, "nint?", "decimal"); unifiedBinaryOps(symbol, "nint?", "System.IntPtr"); unifiedBinaryOps(symbol, "nint?", "System.UIntPtr"); // nint? shiftOp type? unifiedBinaryOps(symbol, "nint?", "bool?"); unifiedBinaryOps(symbol, "nint?", "char?", $"nint nint.{name}(nint left, int right)", null); unifiedBinaryOps(symbol, "nint?", "sbyte?", $"nint nint.{name}(nint left, int right)", null); unifiedBinaryOps(symbol, "nint?", "byte?", $"nint nint.{name}(nint left, int right)", null); unifiedBinaryOps(symbol, "nint?", "short?", $"nint nint.{name}(nint left, int right)", null); unifiedBinaryOps(symbol, "nint?", "ushort?", $"nint nint.{name}(nint left, int right)", null); unifiedBinaryOps(symbol, "nint?", "int?", $"nint nint.{name}(nint left, int right)", null); unifiedBinaryOps(symbol, "nint?", "uint?"); unifiedBinaryOps(symbol, "nint?", "nint?"); unifiedBinaryOps(symbol, "nint?", "nuint?"); unifiedBinaryOps(symbol, "nint?", "long?"); unifiedBinaryOps(symbol, "nint?", "ulong?"); unifiedBinaryOps(symbol, "nint?", "float?"); unifiedBinaryOps(symbol, "nint?", "double?"); unifiedBinaryOps(symbol, "nint?", "decimal?"); unifiedBinaryOps(symbol, "nint?", "System.IntPtr?"); unifiedBinaryOps(symbol, "nint?", "System.UIntPtr?"); // nuint shiftOp type unifiedBinaryOps(symbol, "nuint", "object"); unifiedBinaryOps(symbol, "nuint", "string"); unifiedBinaryOps(symbol, "nuint", "void*", null, null, getBadBinaryOpsDiagnostics(symbol, "nuint", "void*", includeVoidError: true), getBadBinaryOpsDiagnostics(symbol, "void*", "nuint", includeVoidError: true)); unifiedBinaryOps(symbol, "nuint", "bool"); unifiedBinaryOps(symbol, "nuint", "char", $"nuint nuint.{name}(nuint left, int right)", null); unifiedBinaryOps(symbol, "nuint", "sbyte", $"nuint nuint.{name}(nuint left, int right)", null); unifiedBinaryOps(symbol, "nuint", "byte", $"nuint nuint.{name}(nuint left, int right)", null); unifiedBinaryOps(symbol, "nuint", "short", $"nuint nuint.{name}(nuint left, int right)", null); unifiedBinaryOps(symbol, "nuint", "ushort", $"nuint nuint.{name}(nuint left, int right)", null); unifiedBinaryOps(symbol, "nuint", "int", $"nuint nuint.{name}(nuint left, int right)", null); unifiedBinaryOps(symbol, "nuint", "uint"); unifiedBinaryOps(symbol, "nuint", "nint"); unifiedBinaryOps(symbol, "nuint", "nuint"); unifiedBinaryOps(symbol, "nuint", "long"); unifiedBinaryOps(symbol, "nuint", "ulong"); unifiedBinaryOps(symbol, "nuint", "float"); unifiedBinaryOps(symbol, "nuint", "double"); unifiedBinaryOps(symbol, "nuint", "decimal"); unifiedBinaryOps(symbol, "nuint", "System.IntPtr"); unifiedBinaryOps(symbol, "nuint", "System.UIntPtr"); // nuint shiftOp type? unifiedBinaryOps(symbol, "nuint", "bool?"); unifiedBinaryOps(symbol, "nuint", "char?", $"nuint nuint.{name}(nuint left, int right)", null); unifiedBinaryOps(symbol, "nuint", "sbyte?", $"nuint nuint.{name}(nuint left, int right)", null); unifiedBinaryOps(symbol, "nuint", "byte?", $"nuint nuint.{name}(nuint left, int right)", null); unifiedBinaryOps(symbol, "nuint", "short?", $"nuint nuint.{name}(nuint left, int right)", null); unifiedBinaryOps(symbol, "nuint", "ushort?", $"nuint nuint.{name}(nuint left, int right)", null); unifiedBinaryOps(symbol, "nuint", "int?", $"nuint nuint.{name}(nuint left, int right)", null); unifiedBinaryOps(symbol, "nuint", "uint?"); unifiedBinaryOps(symbol, "nuint", "nint?"); unifiedBinaryOps(symbol, "nuint", "nuint?"); unifiedBinaryOps(symbol, "nuint", "long?"); unifiedBinaryOps(symbol, "nuint", "ulong?"); unifiedBinaryOps(symbol, "nuint", "float?"); unifiedBinaryOps(symbol, "nuint", "double?"); unifiedBinaryOps(symbol, "nuint", "decimal?"); unifiedBinaryOps(symbol, "nuint", "System.IntPtr?"); unifiedBinaryOps(symbol, "nuint", "System.UIntPtr?"); // nuint? shiftOp type unifiedBinaryOps(symbol, "nuint?", "object"); unifiedBinaryOps(symbol, "nuint?", "string"); unifiedBinaryOps(symbol, "nuint?", "void*", null, null, getBadBinaryOpsDiagnostics(symbol, "nuint?", "void*", includeVoidError: true), getBadBinaryOpsDiagnostics(symbol, "void*", "nuint?", includeVoidError: true)); unifiedBinaryOps(symbol, "nuint?", "bool"); unifiedBinaryOps(symbol, "nuint?", "char", $"nuint nuint.{name}(nuint left, int right)", null); unifiedBinaryOps(symbol, "nuint?", "sbyte", $"nuint nuint.{name}(nuint left, int right)", null); unifiedBinaryOps(symbol, "nuint?", "byte", $"nuint nuint.{name}(nuint left, int right)", null); unifiedBinaryOps(symbol, "nuint?", "short", $"nuint nuint.{name}(nuint left, int right)", null); unifiedBinaryOps(symbol, "nuint?", "ushort", $"nuint nuint.{name}(nuint left, int right)", null); unifiedBinaryOps(symbol, "nuint?", "int", $"nuint nuint.{name}(nuint left, int right)", null); unifiedBinaryOps(symbol, "nuint?", "uint"); unifiedBinaryOps(symbol, "nuint?", "nint"); unifiedBinaryOps(symbol, "nuint?", "nuint"); unifiedBinaryOps(symbol, "nuint?", "long"); unifiedBinaryOps(symbol, "nuint?", "ulong"); unifiedBinaryOps(symbol, "nuint?", "float"); unifiedBinaryOps(symbol, "nuint?", "double"); unifiedBinaryOps(symbol, "nuint?", "decimal"); unifiedBinaryOps(symbol, "nuint?", "System.IntPtr"); unifiedBinaryOps(symbol, "nuint?", "System.UIntPtr"); // nuint? shiftOp type? unifiedBinaryOps(symbol, "nuint?", "bool?"); unifiedBinaryOps(symbol, "nuint?", "char?", $"nuint nuint.{name}(nuint left, int right)", null); unifiedBinaryOps(symbol, "nuint?", "sbyte?", $"nuint nuint.{name}(nuint left, int right)", null); unifiedBinaryOps(symbol, "nuint?", "byte?", $"nuint nuint.{name}(nuint left, int right)", null); unifiedBinaryOps(symbol, "nuint?", "short?", $"nuint nuint.{name}(nuint left, int right)", null); unifiedBinaryOps(symbol, "nuint?", "ushort?", $"nuint nuint.{name}(nuint left, int right)", null); unifiedBinaryOps(symbol, "nuint?", "int?", $"nuint nuint.{name}(nuint left, int right)", null); unifiedBinaryOps(symbol, "nuint?", "uint?"); unifiedBinaryOps(symbol, "nuint?", "nint?"); unifiedBinaryOps(symbol, "nuint?", "nuint?"); unifiedBinaryOps(symbol, "nuint?", "long?"); unifiedBinaryOps(symbol, "nuint?", "ulong?"); unifiedBinaryOps(symbol, "nuint?", "float?"); unifiedBinaryOps(symbol, "nuint?", "double?"); unifiedBinaryOps(symbol, "nuint?", "decimal?"); unifiedBinaryOps(symbol, "nuint?", "System.IntPtr?"); unifiedBinaryOps(symbol, "nuint?", "System.UIntPtr?"); } foreach ((string symbol, string name) in equalityOperators) { // nint equalityOp type unifiedBinaryOps(symbol, "nint", "object"); unifiedBinaryOps(symbol, "nint", "string"); unifiedBinaryOps(symbol, "nint", "void*", null, null, getBadBinaryOpsDiagnostics(symbol, "nint", "void*"), getBadBinaryOpsDiagnostics(symbol, "void*", "nint")); unifiedBinaryOps(symbol, "nint", "bool"); unifiedBinaryOps(symbol, "nint", "char", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "sbyte", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "byte", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "short", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "ushort", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "int", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "uint", $"bool long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint", "nint", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "nuint", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint")); unifiedBinaryOps(symbol, "nint", "long", $"bool long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint", "ulong", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "ulong"), getAmbiguousBinaryOpsDiagnostics(symbol, "ulong", "nint")); unifiedBinaryOps(symbol, "nint", "float", $"bool float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nint", "double", $"bool double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nint", "decimal", $"bool decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nint", "System.IntPtr", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "System.UIntPtr", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint")); // nint equalityOp type? unifiedBinaryOps(symbol, "nint", "bool?"); unifiedBinaryOps(symbol, "nint", "char?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "sbyte?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "byte?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "short?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "ushort?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "int?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "uint?", $"bool long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint", "nint?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "nuint?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint")); unifiedBinaryOps(symbol, "nint", "long?", $"bool long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint", "ulong?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "ulong?"), getAmbiguousBinaryOpsDiagnostics(symbol, "ulong?", "nint")); unifiedBinaryOps(symbol, "nint", "float?", $"bool float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nint", "double?", $"bool double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nint", "decimal?", $"bool decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nint", "System.IntPtr?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "System.UIntPtr?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint")); unifiedBinaryOps(symbol, "nint", "object"); // nint? equalityOp type unifiedBinaryOps(symbol, "nint?", "string"); unifiedBinaryOps(symbol, "nint?", "void*", null, null, getBadBinaryOpsDiagnostics(symbol, "nint?", "void*"), getBadBinaryOpsDiagnostics(symbol, "void*", "nint?")); unifiedBinaryOps(symbol, "nint?", "bool"); unifiedBinaryOps(symbol, "nint?", "char", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "sbyte", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "byte", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "short", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "ushort", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "int", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "uint", $"bool long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint?", "nint", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "nuint", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint?")); unifiedBinaryOps(symbol, "nint?", "long", $"bool long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint?", "ulong", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "ulong"), getAmbiguousBinaryOpsDiagnostics(symbol, "ulong", "nint?")); unifiedBinaryOps(symbol, "nint?", "float", $"bool float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nint?", "double", $"bool double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nint?", "decimal", $"bool decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nint?", "System.IntPtr", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "System.UIntPtr", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint?")); // nint? equalityOp type? unifiedBinaryOps(symbol, "nint?", "bool?"); unifiedBinaryOps(symbol, "nint?", "char?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "sbyte?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "byte?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "short?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "ushort?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "int?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "uint?", $"bool long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint?", "nint?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "nuint?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint?")); unifiedBinaryOps(symbol, "nint?", "long?", $"bool long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint?", "ulong?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "ulong?"), getAmbiguousBinaryOpsDiagnostics(symbol, "ulong?", "nint?")); unifiedBinaryOps(symbol, "nint?", "float?", $"bool float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nint?", "double?", $"bool double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nint?", "decimal?", $"bool decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nint?", "System.IntPtr?", $"bool nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "System.UIntPtr?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint?")); // nuint equalityOp type unifiedBinaryOps(symbol, "nuint", "object"); unifiedBinaryOps(symbol, "nuint", "string"); unifiedBinaryOps(symbol, "nuint", "void*", null, null, getBadBinaryOpsDiagnostics(symbol, "nuint", "void*"), getBadBinaryOpsDiagnostics(symbol, "void*", "nuint")); unifiedBinaryOps(symbol, "nuint", "bool"); unifiedBinaryOps(symbol, "nuint", "char", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "sbyte", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "sbyte"), getAmbiguousBinaryOpsDiagnostics(symbol, "sbyte", "nuint")); unifiedBinaryOps(symbol, "nuint", "byte", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "short", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "short"), getAmbiguousBinaryOpsDiagnostics(symbol, "short", "nuint")); unifiedBinaryOps(symbol, "nuint", "ushort", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "int", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "int"), getAmbiguousBinaryOpsDiagnostics(symbol, "int", "nuint")); unifiedBinaryOps(symbol, "nuint", "uint", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "nint", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint")); unifiedBinaryOps(symbol, "nuint", "nuint", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "long", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "long"), getAmbiguousBinaryOpsDiagnostics(symbol, "long", "nuint")); unifiedBinaryOps(symbol, "nuint", "ulong", $"bool ulong.{name}(ulong left, ulong right)"); unifiedBinaryOps(symbol, "nuint", "float", $"bool float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nuint", "double", $"bool double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nuint", "decimal", $"bool decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nuint", "System.IntPtr", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint")); unifiedBinaryOps(symbol, "nuint", "System.UIntPtr", $"bool nuint.{name}(nuint left, nuint right)"); // nuint equalityOp type? unifiedBinaryOps(symbol, "nuint", "bool?"); unifiedBinaryOps(symbol, "nuint", "char?", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "sbyte?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "sbyte?"), getAmbiguousBinaryOpsDiagnostics(symbol, "sbyte?", "nuint")); unifiedBinaryOps(symbol, "nuint", "byte?", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "short?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "short?"), getAmbiguousBinaryOpsDiagnostics(symbol, "short?", "nuint")); unifiedBinaryOps(symbol, "nuint", "ushort?", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "int?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "int?"), getAmbiguousBinaryOpsDiagnostics(symbol, "int?", "nuint")); unifiedBinaryOps(symbol, "nuint", "uint?", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "nint?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint")); unifiedBinaryOps(symbol, "nuint", "nuint?", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "long?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "long?"), getAmbiguousBinaryOpsDiagnostics(symbol, "long?", "nuint")); unifiedBinaryOps(symbol, "nuint", "ulong?", $"bool ulong.{name}(ulong left, ulong right)"); unifiedBinaryOps(symbol, "nuint", "float?", $"bool float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nuint", "double?", $"bool double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nuint", "decimal?", $"bool decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nuint", "System.IntPtr?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint", "nint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint")); unifiedBinaryOps(symbol, "nuint", "System.UIntPtr?", $"bool nuint.{name}(nuint left, nuint right)"); // nuint? equalityOp type unifiedBinaryOps(symbol, "nuint?", "object"); unifiedBinaryOps(symbol, "nuint?", "string"); unifiedBinaryOps(symbol, "nuint?", "void*", null, null, getBadBinaryOpsDiagnostics(symbol, "nuint?", "void*"), getBadBinaryOpsDiagnostics(symbol, "void*", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "bool"); unifiedBinaryOps(symbol, "nuint?", "char", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "sbyte", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "sbyte"), getAmbiguousBinaryOpsDiagnostics(symbol, "sbyte", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "byte", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "short", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "short"), getAmbiguousBinaryOpsDiagnostics(symbol, "short", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "ushort", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "int", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "int"), getAmbiguousBinaryOpsDiagnostics(symbol, "int", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "uint", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "nint", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "nuint", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "long", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "long"), getAmbiguousBinaryOpsDiagnostics(symbol, "long", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "ulong", $"bool ulong.{name}(ulong left, ulong right)"); unifiedBinaryOps(symbol, "nuint?", "float", $"bool float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nuint?", "double", $"bool double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nuint?", "decimal", $"bool decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nuint?", "System.IntPtr", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "System.UIntPtr", $"bool nuint.{name}(nuint left, nuint right)"); // nuint? equalityOp type? unifiedBinaryOps(symbol, "nuint?", "bool?"); unifiedBinaryOps(symbol, "nuint?", "char?", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "sbyte?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "sbyte?"), getAmbiguousBinaryOpsDiagnostics(symbol, "sbyte?", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "byte?", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "short?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "short?"), getAmbiguousBinaryOpsDiagnostics(symbol, "short?", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "ushort?", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "int?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "int?"), getAmbiguousBinaryOpsDiagnostics(symbol, "int?", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "uint?", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "nint?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "nuint?", $"bool nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "long?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "long?"), getAmbiguousBinaryOpsDiagnostics(symbol, "long?", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "ulong?", $"bool ulong.{name}(ulong left, ulong right)"); unifiedBinaryOps(symbol, "nuint?", "float?", $"bool float.{name}(float left, float right)"); unifiedBinaryOps(symbol, "nuint?", "double?", $"bool double.{name}(double left, double right)"); unifiedBinaryOps(symbol, "nuint?", "decimal?", $"bool decimal.{name}(decimal left, decimal right)"); unifiedBinaryOps(symbol, "nuint?", "System.IntPtr?", null, null, getAmbiguousBinaryOpsDiagnostics(symbol, "nuint?", "nint?"), getAmbiguousBinaryOpsDiagnostics(symbol, "nint?", "nuint?")); unifiedBinaryOps(symbol, "nuint?", "System.UIntPtr?", $"bool nuint.{name}(nuint left, nuint right)"); } foreach ((string symbol, string name) in logicalOperators) { // nint logicalOp type unifiedBinaryOps(symbol, "nint", "object"); unifiedBinaryOps(symbol, "nint", "string"); unifiedBinaryOps(symbol, "nint", "void*", null, null, getBadBinaryOpsDiagnostics(symbol, "nint", "void*", includeVoidError: true), getBadBinaryOpsDiagnostics(symbol, "void*", "nint", includeVoidError: true)); unifiedBinaryOps(symbol, "nint", "bool"); unifiedBinaryOps(symbol, "nint", "char", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "sbyte", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "byte", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "short", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "ushort", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "int", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "uint", $"long long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint", "nint", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "nuint"); unifiedBinaryOps(symbol, "nint", "long", $"long long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint", "ulong"); unifiedBinaryOps(symbol, "nint", "float"); unifiedBinaryOps(symbol, "nint", "double"); unifiedBinaryOps(symbol, "nint", "decimal"); unifiedBinaryOps(symbol, "nint", "System.IntPtr", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "System.UIntPtr"); // nint logicalOp type? unifiedBinaryOps(symbol, "nint", "bool?"); unifiedBinaryOps(symbol, "nint", "char?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "sbyte?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "byte?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "short?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "ushort?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "int?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "uint?", $"long long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint", "nint?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "nuint?"); unifiedBinaryOps(symbol, "nint", "long?", $"long long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint", "ulong?"); unifiedBinaryOps(symbol, "nint", "float?"); unifiedBinaryOps(symbol, "nint", "double?"); unifiedBinaryOps(symbol, "nint", "decimal?"); unifiedBinaryOps(symbol, "nint", "System.IntPtr?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint", "System.UIntPtr?"); unifiedBinaryOps(symbol, "nint", "object"); // nint? logicalOp type unifiedBinaryOps(symbol, "nint?", "string"); unifiedBinaryOps(symbol, "nint?", "void*", null, null, getBadBinaryOpsDiagnostics(symbol, "nint?", "void*", includeVoidError: true), getBadBinaryOpsDiagnostics(symbol, "void*", "nint?", includeVoidError: true)); unifiedBinaryOps(symbol, "nint?", "bool"); unifiedBinaryOps(symbol, "nint?", "char", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "sbyte", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "byte", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "short", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "ushort", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "int", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "uint", $"long long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint?", "nint", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "nuint"); unifiedBinaryOps(symbol, "nint?", "long", $"long long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint?", "ulong"); unifiedBinaryOps(symbol, "nint?", "float"); unifiedBinaryOps(symbol, "nint?", "double"); unifiedBinaryOps(symbol, "nint?", "decimal"); unifiedBinaryOps(symbol, "nint?", "System.IntPtr", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "System.UIntPtr"); // nint? logicalOp type? unifiedBinaryOps(symbol, "nint?", "bool?"); unifiedBinaryOps(symbol, "nint?", "char?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "sbyte?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "byte?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "short?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "ushort?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "int?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "uint?", $"long long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint?", "nint?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "nuint?"); unifiedBinaryOps(symbol, "nint?", "long?", $"long long.{name}(long left, long right)"); unifiedBinaryOps(symbol, "nint?", "ulong?"); unifiedBinaryOps(symbol, "nint?", "float?"); unifiedBinaryOps(symbol, "nint?", "double?"); unifiedBinaryOps(symbol, "nint?", "decimal?"); unifiedBinaryOps(symbol, "nint?", "System.IntPtr?", $"nint nint.{name}(nint left, nint right)"); unifiedBinaryOps(symbol, "nint?", "System.UIntPtr?"); // nuint logicalOp type unifiedBinaryOps(symbol, "nuint", "object"); unifiedBinaryOps(symbol, "nuint", "string"); unifiedBinaryOps(symbol, "nuint", "void*", null, null, getBadBinaryOpsDiagnostics(symbol, "nuint", "void*", includeVoidError: true), getBadBinaryOpsDiagnostics(symbol, "void*", "nuint", includeVoidError: true)); unifiedBinaryOps(symbol, "nuint", "bool"); unifiedBinaryOps(symbol, "nuint", "char", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "sbyte"); unifiedBinaryOps(symbol, "nuint", "byte", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "short"); unifiedBinaryOps(symbol, "nuint", "ushort", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "int"); unifiedBinaryOps(symbol, "nuint", "uint", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "nint"); unifiedBinaryOps(symbol, "nuint", "nuint", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "long"); unifiedBinaryOps(symbol, "nuint", "ulong", $"ulong ulong.{name}(ulong left, ulong right)"); unifiedBinaryOps(symbol, "nuint", "float"); unifiedBinaryOps(symbol, "nuint", "double"); unifiedBinaryOps(symbol, "nuint", "decimal"); unifiedBinaryOps(symbol, "nuint", "System.IntPtr"); unifiedBinaryOps(symbol, "nuint", "System.UIntPtr", $"nuint nuint.{name}(nuint left, nuint right)"); // nuint logicalOp type? unifiedBinaryOps(symbol, "nuint", "bool?"); unifiedBinaryOps(symbol, "nuint", "char?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "sbyte?"); unifiedBinaryOps(symbol, "nuint", "byte?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "short?"); unifiedBinaryOps(symbol, "nuint", "ushort?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "int?"); unifiedBinaryOps(symbol, "nuint", "uint?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "nint?"); unifiedBinaryOps(symbol, "nuint", "nuint?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint", "long?"); unifiedBinaryOps(symbol, "nuint", "ulong?", $"ulong ulong.{name}(ulong left, ulong right)"); unifiedBinaryOps(symbol, "nuint", "float?"); unifiedBinaryOps(symbol, "nuint", "double?"); unifiedBinaryOps(symbol, "nuint", "decimal?"); unifiedBinaryOps(symbol, "nuint", "System.IntPtr?"); unifiedBinaryOps(symbol, "nuint", "System.UIntPtr?", $"nuint nuint.{name}(nuint left, nuint right)"); // nuint? logicalOp type unifiedBinaryOps(symbol, "nuint?", "object"); unifiedBinaryOps(symbol, "nuint?", "string"); unifiedBinaryOps(symbol, "nuint?", "void*", null, null, getBadBinaryOpsDiagnostics(symbol, "nuint?", "void*", includeVoidError: true), getBadBinaryOpsDiagnostics(symbol, "void*", "nuint?", includeVoidError: true)); unifiedBinaryOps(symbol, "nuint?", "bool"); unifiedBinaryOps(symbol, "nuint?", "char", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "sbyte"); unifiedBinaryOps(symbol, "nuint?", "byte", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "short"); unifiedBinaryOps(symbol, "nuint?", "ushort", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "int"); unifiedBinaryOps(symbol, "nuint?", "uint", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "nint"); unifiedBinaryOps(symbol, "nuint?", "nuint", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "long"); unifiedBinaryOps(symbol, "nuint?", "ulong", $"ulong ulong.{name}(ulong left, ulong right)"); unifiedBinaryOps(symbol, "nuint?", "float"); unifiedBinaryOps(symbol, "nuint?", "double"); unifiedBinaryOps(symbol, "nuint?", "decimal"); unifiedBinaryOps(symbol, "nuint?", "System.IntPtr"); unifiedBinaryOps(symbol, "nuint?", "System.UIntPtr", $"nuint nuint.{name}(nuint left, nuint right)"); // nuint? logicalOp type? unifiedBinaryOps(symbol, "nuint?", "bool?"); unifiedBinaryOps(symbol, "nuint?", "char?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "sbyte?"); unifiedBinaryOps(symbol, "nuint?", "byte?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "short?"); unifiedBinaryOps(symbol, "nuint?", "ushort?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "int?"); unifiedBinaryOps(symbol, "nuint?", "uint?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "nint?"); unifiedBinaryOps(symbol, "nuint?", "nuint?", $"nuint nuint.{name}(nuint left, nuint right)"); unifiedBinaryOps(symbol, "nuint?", "long?"); unifiedBinaryOps(symbol, "nuint?", "ulong?", $"ulong ulong.{name}(ulong left, ulong right)"); unifiedBinaryOps(symbol, "nuint?", "float?"); unifiedBinaryOps(symbol, "nuint?", "double?"); unifiedBinaryOps(symbol, "nuint?", "decimal?"); unifiedBinaryOps(symbol, "nuint?", "System.IntPtr?"); unifiedBinaryOps(symbol, "nuint?", "System.UIntPtr?", $"nuint nuint.{name}(nuint left, nuint right)"); } void binaryOperator(string op, string leftType, string rightType, string expectedSymbol, DiagnosticDescription[] expectedDiagnostics) { bool useUnsafeContext = useUnsafe(leftType) || useUnsafe(rightType); string source = $@"class Program {{ static {(useUnsafeContext ? "unsafe " : "")}object Evaluate({leftType} x, {rightType} y) {{ return x {op} y; }} }}"; var comp = CreateCompilation(source, options: TestOptions.ReleaseDll.WithAllowUnsafe(useUnsafeContext), parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(expectedDiagnostics); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var expr = tree.GetRoot().DescendantNodes().OfType<BinaryExpressionSyntax>().Single(); var symbolInfo = model.GetSymbolInfo(expr); Assert.Equal(expectedSymbol, symbolInfo.Symbol?.ToDisplayString(TestFormat.WithMiscellaneousOptions(SymbolDisplayMiscellaneousOptions.UseSpecialTypes))); if (expectedDiagnostics.Length == 0) { CompileAndVerify(comp, verify: Verification.FailsPEVerify); } static bool useUnsafe(string type) => type == "void*"; } } [Fact] public void BinaryOperators_NInt() { var source = @"using System; class Program { static nint Add(nint x, nint y) => x + y; static nint Subtract(nint x, nint y) => x - y; static nint Multiply(nint x, nint y) => x * y; static nint Divide(nint x, nint y) => x / y; static nint Mod(nint x, nint y) => x % y; static bool Equals(nint x, nint y) => x == y; static bool NotEquals(nint x, nint y) => x != y; static bool LessThan(nint x, nint y) => x < y; static bool LessThanOrEqual(nint x, nint y) => x <= y; static bool GreaterThan(nint x, nint y) => x > y; static bool GreaterThanOrEqual(nint x, nint y) => x >= y; static nint And(nint x, nint y) => x & y; static nint Or(nint x, nint y) => x | y; static nint Xor(nint x, nint y) => x ^ y; static nint ShiftLeft(nint x, int y) => x << y; static nint ShiftRight(nint x, int y) => x >> y; static void Main() { Console.WriteLine(Add(3, 4)); Console.WriteLine(Subtract(3, 4)); Console.WriteLine(Multiply(3, 4)); Console.WriteLine(Divide(5, 2)); Console.WriteLine(Mod(5, 2)); Console.WriteLine(Equals(3, 4)); Console.WriteLine(NotEquals(3, 4)); Console.WriteLine(LessThan(3, 4)); Console.WriteLine(LessThanOrEqual(3, 4)); Console.WriteLine(GreaterThan(3, 4)); Console.WriteLine(GreaterThanOrEqual(3, 4)); Console.WriteLine(And(3, 5)); Console.WriteLine(Or(3, 5)); Console.WriteLine(Xor(3, 5)); Console.WriteLine(ShiftLeft(35, 4)); Console.WriteLine(ShiftRight(35, 4)); } }"; var comp = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); var verifier = CompileAndVerify(comp, verify: Verification.FailsPEVerify, expectedOutput: IncludeExpectedOutput( @"7 -1 12 2 1 False True True True False False 1 7 6 560 2")); verifier.VerifyIL("Program.Add", @"{ // Code size 4 (0x4) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: add IL_0003: ret }", ilFormat: ILFormat); verifier.VerifyIL("Program.Subtract", @"{ // Code size 4 (0x4) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: sub IL_0003: ret }", ilFormat: ILFormat); verifier.VerifyIL("Program.Multiply", @"{ // Code size 4 (0x4) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: mul IL_0003: ret }", ilFormat: ILFormat); verifier.VerifyIL("Program.Divide", @"{ // Code size 4 (0x4) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: div IL_0003: ret }", ilFormat: ILFormat); verifier.VerifyIL("Program.Mod", @"{ // Code size 4 (0x4) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: rem IL_0003: ret }", ilFormat: ILFormat); verifier.VerifyIL("Program.Equals", @"{ // Code size 5 (0x5) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: ceq IL_0004: ret }", ilFormat: ILFormat); verifier.VerifyIL("Program.NotEquals", @"{ // Code size 8 (0x8) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: ceq IL_0004: ldc.i4.0 IL_0005: ceq IL_0007: ret }", ilFormat: ILFormat); verifier.VerifyIL("Program.LessThan", @"{ // Code size 5 (0x5) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: clt IL_0004: ret }", ilFormat: ILFormat); verifier.VerifyIL("Program.LessThanOrEqual", @"{ // Code size 8 (0x8) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: cgt IL_0004: ldc.i4.0 IL_0005: ceq IL_0007: ret }", ilFormat: ILFormat); verifier.VerifyIL("Program.GreaterThan", @"{ // Code size 5 (0x5) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: cgt IL_0004: ret }", ilFormat: ILFormat); verifier.VerifyIL("Program.GreaterThanOrEqual", @"{ // Code size 8 (0x8) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: clt IL_0004: ldc.i4.0 IL_0005: ceq IL_0007: ret }", ilFormat: ILFormat); verifier.VerifyIL("Program.And", @"{ // Code size 4 (0x4) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: and IL_0003: ret }", ilFormat: ILFormat); verifier.VerifyIL("Program.Or", @"{ // Code size 4 (0x4) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: or IL_0003: ret }", ilFormat: ILFormat); verifier.VerifyIL("Program.Xor", @"{ // Code size 4 (0x4) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: xor IL_0003: ret }", ilFormat: ILFormat); verifier.VerifyIL("Program.ShiftLeft", @"{ // Code size 15 (0xf) .maxstack 4 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: sizeof ""nint"" IL_0008: ldc.i4.8 IL_0009: mul IL_000a: ldc.i4.1 IL_000b: sub IL_000c: and IL_000d: shl IL_000e: ret }", ilFormat: ILFormat); verifier.VerifyIL("Program.ShiftRight", @"{ // Code size 15 (0xf) .maxstack 4 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: sizeof ""nint"" IL_0008: ldc.i4.8 IL_0009: mul IL_000a: ldc.i4.1 IL_000b: sub IL_000c: and IL_000d: shr IL_000e: ret }", ilFormat: ILFormat); } [Fact] public void BinaryOperators_NUInt() { var source = @"using System; class Program { static UIntPtr Add(UIntPtr x, UIntPtr y) => x + y; static UIntPtr Subtract(UIntPtr x, UIntPtr y) => x - y; static UIntPtr Multiply(UIntPtr x, UIntPtr y) => x * y; static UIntPtr Divide(UIntPtr x, UIntPtr y) => x / y; static UIntPtr Mod(UIntPtr x, UIntPtr y) => x % y; static bool Equals(UIntPtr x, UIntPtr y) => x == y; static bool NotEquals(UIntPtr x, UIntPtr y) => x != y; static bool LessThan(UIntPtr x, UIntPtr y) => x < y; static bool LessThanOrEqual(UIntPtr x, UIntPtr y) => x <= y; static bool GreaterThan(UIntPtr x, UIntPtr y) => x > y; static bool GreaterThanOrEqual(UIntPtr x, UIntPtr y) => x >= y; static UIntPtr And(UIntPtr x, UIntPtr y) => x & y; static UIntPtr Or(UIntPtr x, UIntPtr y) => x | y; static UIntPtr Xor(UIntPtr x, UIntPtr y) => x ^ y; static UIntPtr ShiftLeft(UIntPtr x, int y) => x << y; static UIntPtr ShiftRight(UIntPtr x, int y) => x >> y; static void Main() { Console.WriteLine(Add(3, 4)); Console.WriteLine(Subtract(4, 3)); Console.WriteLine(Multiply(3, 4)); Console.WriteLine(Divide(5, 2)); Console.WriteLine(Mod(5, 2)); Console.WriteLine(Equals(3, 4)); Console.WriteLine(NotEquals(3, 4)); Console.WriteLine(LessThan(3, 4)); Console.WriteLine(LessThanOrEqual(3, 4)); Console.WriteLine(GreaterThan(3, 4)); Console.WriteLine(GreaterThanOrEqual(3, 4)); Console.WriteLine(And(3, 5)); Console.WriteLine(Or(3, 5)); Console.WriteLine(Xor(3, 5)); Console.WriteLine(ShiftLeft(35, 4)); Console.WriteLine(ShiftRight(35, 4)); } }"; var comp = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); var verifier = CompileAndVerify(comp, verify: Verification.FailsPEVerify, expectedOutput: IncludeExpectedOutput( @"7 1 12 2 1 False True True True False False 1 7 6 560 2")); verifier.VerifyIL("Program.Add", @"{ // Code size 4 (0x4) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: add IL_0003: ret }"); verifier.VerifyIL("Program.Subtract", @"{ // Code size 4 (0x4) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: sub IL_0003: ret }"); verifier.VerifyIL("Program.Multiply", @"{ // Code size 4 (0x4) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: mul IL_0003: ret }"); verifier.VerifyIL("Program.Divide", @"{ // Code size 4 (0x4) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: div.un IL_0003: ret }"); verifier.VerifyIL("Program.Mod", @"{ // Code size 4 (0x4) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: rem.un IL_0003: ret }"); verifier.VerifyIL("Program.Equals", @"{ // Code size 5 (0x5) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: ceq IL_0004: ret }"); verifier.VerifyIL("Program.NotEquals", @"{ // Code size 8 (0x8) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: ceq IL_0004: ldc.i4.0 IL_0005: ceq IL_0007: ret }"); verifier.VerifyIL("Program.LessThan", @"{ // Code size 5 (0x5) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: clt.un IL_0004: ret }"); verifier.VerifyIL("Program.LessThanOrEqual", @"{ // Code size 8 (0x8) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: cgt.un IL_0004: ldc.i4.0 IL_0005: ceq IL_0007: ret }"); verifier.VerifyIL("Program.GreaterThan", @"{ // Code size 5 (0x5) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: cgt.un IL_0004: ret }"); verifier.VerifyIL("Program.GreaterThanOrEqual", @"{ // Code size 8 (0x8) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: clt.un IL_0004: ldc.i4.0 IL_0005: ceq IL_0007: ret }"); verifier.VerifyIL("Program.And", @"{ // Code size 4 (0x4) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: and IL_0003: ret }"); verifier.VerifyIL("Program.Or", @"{ // Code size 4 (0x4) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: or IL_0003: ret }"); verifier.VerifyIL("Program.Xor", @"{ // Code size 4 (0x4) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: xor IL_0003: ret }"); verifier.VerifyIL("Program.ShiftLeft", @"{ // Code size 15 (0xf) .maxstack 4 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: sizeof ""nuint"" IL_0008: ldc.i4.8 IL_0009: mul IL_000a: ldc.i4.1 IL_000b: sub IL_000c: and IL_000d: shl IL_000e: ret }", ilFormat: ILFormat); verifier.VerifyIL("Program.ShiftRight", @"{ // Code size 15 (0xf) .maxstack 4 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: sizeof ""nuint"" IL_0008: ldc.i4.8 IL_0009: mul IL_000a: ldc.i4.1 IL_000b: sub IL_000c: and IL_000d: shr.un IL_000e: ret }", ilFormat: ILFormat); } [Fact] public void BinaryOperators_NInt_Checked() { var source = @"using System; class Program { static IntPtr Add(IntPtr x, IntPtr y) => checked(x + y); static IntPtr Subtract(IntPtr x, IntPtr y) => checked(x - y); static IntPtr Multiply(IntPtr x, IntPtr y) => checked(x * y); static IntPtr Divide(IntPtr x, IntPtr y) => checked(x / y); static IntPtr Mod(IntPtr x, IntPtr y) => checked(x % y); static void Main() { Console.WriteLine(Add(3, 4)); Console.WriteLine(Subtract(3, 4)); Console.WriteLine(Multiply(3, 4)); Console.WriteLine(Divide(5, 2)); Console.WriteLine(Mod(5, 2)); } }"; var comp = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); var verifier = CompileAndVerify(comp, verify: Verification.FailsPEVerify, expectedOutput: IncludeExpectedOutput( @"7 -1 12 2 1")); verifier.VerifyIL("Program.Add", @"{ // Code size 4 (0x4) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: add.ovf IL_0003: ret }"); verifier.VerifyIL("Program.Subtract", @"{ // Code size 4 (0x4) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: sub.ovf IL_0003: ret }"); verifier.VerifyIL("Program.Multiply", @"{ // Code size 4 (0x4) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: mul.ovf IL_0003: ret }"); verifier.VerifyIL("Program.Divide", @"{ // Code size 4 (0x4) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: div IL_0003: ret }"); verifier.VerifyIL("Program.Mod", @"{ // Code size 4 (0x4) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: rem IL_0003: ret }"); } [Fact] public void BinaryOperators_NUInt_Checked() { var source = @"using System; class Program { static UIntPtr Add(UIntPtr x, UIntPtr y) => checked(x + y); static UIntPtr Subtract(UIntPtr x, UIntPtr y) => checked(x - y); static UIntPtr Multiply(UIntPtr x, UIntPtr y) => checked(x * y); static UIntPtr Divide(UIntPtr x, UIntPtr y) => checked(x / y); static UIntPtr Mod(UIntPtr x, UIntPtr y) => checked(x % y); static void Main() { Console.WriteLine(Add(3, 4)); Console.WriteLine(Subtract(4, 3)); Console.WriteLine(Multiply(3, 4)); Console.WriteLine(Divide(5, 2)); Console.WriteLine(Mod(5, 2)); } }"; var comp = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); var verifier = CompileAndVerify(comp, verify: Verification.FailsPEVerify, expectedOutput: IncludeExpectedOutput( @"7 1 12 2 1")); verifier.VerifyIL("Program.Add", @"{ // Code size 4 (0x4) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: add.ovf.un IL_0003: ret }"); verifier.VerifyIL("Program.Subtract", @"{ // Code size 4 (0x4) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: sub.ovf.un IL_0003: ret }"); verifier.VerifyIL("Program.Multiply", @"{ // Code size 4 (0x4) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: mul.ovf.un IL_0003: ret }"); verifier.VerifyIL("Program.Divide", @"{ // Code size 4 (0x4) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: div.un IL_0003: ret }"); verifier.VerifyIL("Program.Mod", @"{ // Code size 4 (0x4) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: rem.un IL_0003: ret }"); } [Fact] public void ConstantFolding_01() { const string intMinValue = "-2147483648"; const string intMaxValue = "2147483647"; const string uintMaxValue = "4294967295"; const string ulongMaxValue = "18446744073709551615"; unaryOperator("System.IntPtr", "+", intMinValue, intMinValue); unaryOperator("System.IntPtr", "+", intMaxValue, intMaxValue); unaryOperator("System.UIntPtr", "+", "0", "0"); unaryOperator("System.UIntPtr", "+", uintMaxValue, uintMaxValue); unaryOperator("System.IntPtr", "-", "-1", "1"); unaryOperatorCheckedOverflow("System.IntPtr", "-", intMinValue, IntPtr.Size == 4 ? "-2147483648" : "2147483648", IntPtr.Size == 4 ? "System.OverflowException" : "2147483648"); unaryOperator("System.IntPtr", "-", "-2147483647", intMaxValue); unaryOperator("System.IntPtr", "-", intMaxValue, "-2147483647"); unaryOperator("System.UIntPtr", "-", "0", null, getBadUnaryOpDiagnostics); unaryOperator("System.UIntPtr", "-", "1", null, getBadUnaryOpDiagnostics); unaryOperator("System.UIntPtr", "-", uintMaxValue, null, getBadUnaryOpDiagnostics); unaryOperatorNotConstant("System.IntPtr", "~", "0", "-1"); unaryOperatorNotConstant("System.IntPtr", "~", "-1", "0"); unaryOperatorNotConstant("System.IntPtr", "~", intMinValue, "2147483647"); unaryOperatorNotConstant("System.IntPtr", "~", intMaxValue, "-2147483648"); unaryOperatorNotConstant("System.UIntPtr", "~", "0", IntPtr.Size == 4 ? uintMaxValue : ulongMaxValue); unaryOperatorNotConstant("System.UIntPtr", "~", uintMaxValue, IntPtr.Size == 4 ? "0" : "18446744069414584320"); binaryOperatorCheckedOverflow("System.IntPtr", "+", "System.IntPtr", intMinValue, "System.IntPtr", "-1", IntPtr.Size == 4 ? "2147483647" : "-2147483649", IntPtr.Size == 4 ? "System.OverflowException" : "-2147483649"); binaryOperator("System.IntPtr", "+", "System.IntPtr", "-2147483647", "System.IntPtr", "-1", intMinValue); binaryOperatorCheckedOverflow("System.IntPtr", "+", "System.IntPtr", "1", "System.IntPtr", intMaxValue, IntPtr.Size == 4 ? "-2147483648" : "2147483648", IntPtr.Size == 4 ? "System.OverflowException" : "2147483648"); binaryOperator("System.IntPtr", "+", "System.IntPtr", "1", "System.IntPtr", "2147483646", intMaxValue); binaryOperatorCheckedOverflow("System.UIntPtr", "+", "System.UIntPtr", "1", "System.UIntPtr", uintMaxValue, IntPtr.Size == 4 ? "0" : "4294967296", IntPtr.Size == 4 ? "System.OverflowException" : "4294967296"); binaryOperator("System.UIntPtr", "+", "System.UIntPtr", "1", "System.UIntPtr", "4294967294", uintMaxValue); binaryOperatorCheckedOverflow("System.IntPtr", "-", "System.IntPtr", intMinValue, "System.IntPtr", "1", IntPtr.Size == 4 ? "2147483647" : "-2147483649", IntPtr.Size == 4 ? "System.OverflowException" : "-2147483649"); binaryOperator("System.IntPtr", "-", "System.IntPtr", intMinValue, "System.IntPtr", "-1", "-2147483647"); binaryOperator("System.IntPtr", "-", "System.IntPtr", "-1", "System.IntPtr", intMaxValue, intMinValue); binaryOperatorCheckedOverflow("System.IntPtr", "-", "System.IntPtr", "-2", "System.IntPtr", intMaxValue, IntPtr.Size == 4 ? "2147483647" : "-2147483649", IntPtr.Size == 4 ? "System.OverflowException" : "-2147483649"); binaryOperatorCheckedOverflow("System.UIntPtr", "-", "System.UIntPtr", "0", "System.UIntPtr", "1", IntPtr.Size == 4 ? uintMaxValue : ulongMaxValue, "System.OverflowException"); binaryOperator("System.UIntPtr", "-", "System.UIntPtr", uintMaxValue, "System.UIntPtr", uintMaxValue, "0"); binaryOperatorCheckedOverflow("System.IntPtr", "*", "System.IntPtr", intMinValue, "System.IntPtr", "2", IntPtr.Size == 4 ? "0" : "-4294967296", IntPtr.Size == 4 ? "System.OverflowException" : "-4294967296"); binaryOperatorCheckedOverflow("System.IntPtr", "*", "System.IntPtr", intMinValue, "System.IntPtr", "-1", IntPtr.Size == 4 ? "-2147483648" : "2147483648", IntPtr.Size == 4 ? "System.OverflowException" : "2147483648"); binaryOperator("System.IntPtr", "*", "System.IntPtr", "-1", "System.IntPtr", intMaxValue, "-2147483647"); binaryOperatorCheckedOverflow("System.IntPtr", "*", "System.IntPtr", "2", "System.IntPtr", intMaxValue, IntPtr.Size == 4 ? "-2" : "4294967294", IntPtr.Size == 4 ? "System.OverflowException" : "4294967294"); binaryOperatorCheckedOverflow("System.UIntPtr", "*", "System.UIntPtr", uintMaxValue, "System.UIntPtr", "2", IntPtr.Size == 4 ? "4294967294" : "8589934590", IntPtr.Size == 4 ? "System.OverflowException" : "8589934590"); binaryOperator("System.UIntPtr", "*", "System.UIntPtr", intMaxValue, "System.UIntPtr", "2", "4294967294"); binaryOperator("System.IntPtr", "/", "System.IntPtr", intMinValue, "System.IntPtr", "1", intMinValue); binaryOperatorCheckedOverflow("System.IntPtr", "/", "System.IntPtr", intMinValue, "System.IntPtr", "-1", IntPtr.Size == 4 ? "System.OverflowException" : "2147483648", IntPtr.Size == 4 ? "System.OverflowException" : "2147483648"); binaryOperator("System.IntPtr", "/", "System.IntPtr", "1", "System.IntPtr", "0", null, getIntDivByZeroDiagnostics); binaryOperator("System.IntPtr", "/", "System.IntPtr", "0", "System.IntPtr", "0", null, getIntDivByZeroDiagnostics); binaryOperator("System.UIntPtr", "/", "System.UIntPtr", uintMaxValue, "System.UIntPtr", "1", uintMaxValue); binaryOperator("System.UIntPtr", "/", "System.UIntPtr", uintMaxValue, "System.UIntPtr", "2", intMaxValue); binaryOperator("System.UIntPtr", "/", "System.UIntPtr", "1", "System.UIntPtr", "0", null, getIntDivByZeroDiagnostics); binaryOperator("System.UIntPtr", "/", "System.UIntPtr", "0", "System.UIntPtr", "0", null, getIntDivByZeroDiagnostics); binaryOperator("System.IntPtr", "%", "System.IntPtr", intMinValue, "System.IntPtr", "2", "0"); binaryOperator("System.IntPtr", "%", "System.IntPtr", intMinValue, "System.IntPtr", "-2", "0"); binaryOperatorCheckedOverflow("System.IntPtr", "%", "System.IntPtr", intMinValue, "System.IntPtr", "-1", IntPtr.Size == 4 ? "System.OverflowException" : "0", IntPtr.Size == 4 ? "System.OverflowException" : "0"); binaryOperator("System.IntPtr", "%", "System.IntPtr", "1", "System.IntPtr", "0", null, getIntDivByZeroDiagnostics); binaryOperator("System.IntPtr", "%", "System.IntPtr", "0", "System.IntPtr", "0", null, getIntDivByZeroDiagnostics); binaryOperator("System.UIntPtr", "%", "System.UIntPtr", uintMaxValue, "System.UIntPtr", "1", "0"); binaryOperator("System.UIntPtr", "%", "System.UIntPtr", uintMaxValue, "System.UIntPtr", "2", "1"); binaryOperator("System.UIntPtr", "%", "System.UIntPtr", "1", "System.UIntPtr", "0", null, getIntDivByZeroDiagnostics); binaryOperator("System.UIntPtr", "%", "System.UIntPtr", "0", "System.UIntPtr", "0", null, getIntDivByZeroDiagnostics); binaryOperator("bool", "<", "System.IntPtr", intMinValue, "System.IntPtr", intMinValue, "False"); binaryOperator("bool", "<", "System.IntPtr", intMinValue, "System.IntPtr", intMaxValue, "True"); binaryOperator("bool", "<", "System.IntPtr", intMaxValue, "System.IntPtr", intMaxValue, "False"); binaryOperator("bool", "<", "System.UIntPtr", "0", "System.UIntPtr", "0", "False"); binaryOperator("bool", "<", "System.UIntPtr", "0", "System.UIntPtr", uintMaxValue, "True"); binaryOperator("bool", "<", "System.UIntPtr", uintMaxValue, "System.UIntPtr", uintMaxValue, "False"); binaryOperator("bool", "<=", "System.IntPtr", intMinValue, "System.IntPtr", intMinValue, "True"); binaryOperator("bool", "<=", "System.IntPtr", intMaxValue, "System.IntPtr", intMinValue, "False"); binaryOperator("bool", "<=", "System.IntPtr", intMaxValue, "System.IntPtr", intMaxValue, "True"); binaryOperator("bool", "<=", "System.UIntPtr", "0", "System.UIntPtr", "0", "True"); binaryOperator("bool", "<=", "System.UIntPtr", uintMaxValue, "System.UIntPtr", "0", "False"); binaryOperator("bool", "<=", "System.UIntPtr", uintMaxValue, "System.UIntPtr", uintMaxValue, "True"); binaryOperator("bool", ">", "System.IntPtr", intMinValue, "System.IntPtr", intMinValue, "False"); binaryOperator("bool", ">", "System.IntPtr", intMaxValue, "System.IntPtr", intMinValue, "True"); binaryOperator("bool", ">", "System.IntPtr", intMaxValue, "System.IntPtr", intMaxValue, "False"); binaryOperator("bool", ">", "System.UIntPtr", "0", "System.UIntPtr", "0", "False"); binaryOperator("bool", ">", "System.UIntPtr", uintMaxValue, "System.UIntPtr", "0", "True"); binaryOperator("bool", ">", "System.UIntPtr", uintMaxValue, "System.UIntPtr", uintMaxValue, "False"); binaryOperator("bool", ">=", "System.IntPtr", intMinValue, "System.IntPtr", intMinValue, "True"); binaryOperator("bool", ">=", "System.IntPtr", intMinValue, "System.IntPtr", intMaxValue, "False"); binaryOperator("bool", ">=", "System.IntPtr", intMaxValue, "System.IntPtr", intMaxValue, "True"); binaryOperator("bool", ">=", "System.UIntPtr", "0", "System.UIntPtr", "0", "True"); binaryOperator("bool", ">=", "System.UIntPtr", "0", "System.UIntPtr", uintMaxValue, "False"); binaryOperator("bool", ">=", "System.UIntPtr", uintMaxValue, "System.UIntPtr", uintMaxValue, "True"); binaryOperator("bool", "==", "System.IntPtr", intMinValue, "System.IntPtr", intMinValue, "True"); binaryOperator("bool", "==", "System.IntPtr", intMinValue, "System.IntPtr", intMaxValue, "False"); binaryOperator("bool", "==", "System.IntPtr", intMaxValue, "System.IntPtr", intMaxValue, "True"); binaryOperator("bool", "==", "System.UIntPtr", "0", "System.UIntPtr", "0", "True"); binaryOperator("bool", "==", "System.UIntPtr", "0", "System.UIntPtr", uintMaxValue, "False"); binaryOperator("bool", "==", "System.UIntPtr", uintMaxValue, "System.UIntPtr", uintMaxValue, "True"); binaryOperator("bool", "!=", "System.IntPtr", intMinValue, "System.IntPtr", intMinValue, "False"); binaryOperator("bool", "!=", "System.IntPtr", intMinValue, "System.IntPtr", intMaxValue, "True"); binaryOperator("bool", "!=", "System.IntPtr", intMaxValue, "System.IntPtr", intMaxValue, "False"); binaryOperator("bool", "!=", "System.UIntPtr", "0", "System.UIntPtr", "0", "False"); binaryOperator("bool", "!=", "System.UIntPtr", "0", "System.UIntPtr", uintMaxValue, "True"); binaryOperator("bool", "!=", "System.UIntPtr", uintMaxValue, "System.UIntPtr", uintMaxValue, "False"); binaryOperator("System.IntPtr", "<<", "System.IntPtr", intMinValue, "int", "0", intMinValue); binaryOperatorNotConstant("System.IntPtr", "<<", "System.IntPtr", intMinValue, "int", "1", IntPtr.Size == 4 ? "0" : "-4294967296"); binaryOperatorNotConstant("System.IntPtr", "<<", "System.IntPtr", "1", "int", "32", IntPtr.Size == 4 ? "1" : "4294967296"); binaryOperator("System.IntPtr", "<<", "System.IntPtr", "-1", "int", "31", intMinValue); binaryOperatorNotConstant("System.IntPtr", "<<", "System.IntPtr", "-1", "int", "32", IntPtr.Size == 4 ? "-1" : "-4294967296"); binaryOperator("System.UIntPtr", "<<", "System.UIntPtr", "0", "int", "1", "0"); binaryOperatorNotConstant("System.UIntPtr", "<<", "System.UIntPtr", uintMaxValue, "int", "1", IntPtr.Size == 4 ? "4294967294" : "8589934590"); binaryOperator("System.UIntPtr", "<<", "System.UIntPtr", "1", "int", "31", "2147483648"); binaryOperatorNotConstant("System.UIntPtr", "<<", "System.UIntPtr", "1", "int", "32", IntPtr.Size == 4 ? "1" : "4294967296"); binaryOperator("System.IntPtr", ">>", "System.IntPtr", intMinValue, "int", "0", intMinValue); binaryOperator("System.IntPtr", ">>", "System.IntPtr", intMinValue, "int", "1", "-1073741824"); binaryOperator("System.IntPtr", ">>", "System.IntPtr", "-1", "int", "31", "-1"); binaryOperator("System.IntPtr", ">>", "System.IntPtr", "-1", "int", "32", "-1"); binaryOperatorNotConstant("System.IntPtr", ">>", "System.IntPtr", intMaxValue, "int", "32", IntPtr.Size == 4 ? intMaxValue : "0"); binaryOperator("System.UIntPtr", ">>", "System.UIntPtr", "0", "int", "1", "0"); binaryOperator("System.UIntPtr", ">>", "System.UIntPtr", uintMaxValue, "int", "1", intMaxValue); binaryOperator("System.UIntPtr", ">>", "System.UIntPtr", "1", "int", "31", "0"); binaryOperatorNotConstant("System.UIntPtr", ">>", "System.UIntPtr", "1", "int", "32", IntPtr.Size == 4 ? "1" : "0"); binaryOperatorNotConstant("System.IntPtr", ">>>", "System.IntPtr", "-1", "int", "32", IntPtr.Size == 4 ? "-1" : uintMaxValue); binaryOperatorNotConstant("System.UIntPtr", ">>>", "System.UIntPtr", "1", "int", "32", IntPtr.Size == 4 ? "1" : "0"); binaryOperator("System.IntPtr", "&", "System.IntPtr", intMinValue, "System.IntPtr", "0", "0"); binaryOperator("System.IntPtr", "&", "System.IntPtr", intMinValue, "System.IntPtr", "-1", intMinValue); binaryOperator("System.IntPtr", "&", "System.IntPtr", intMinValue, "System.IntPtr", intMaxValue, "0"); binaryOperator("System.UIntPtr", "&", "System.UIntPtr", "0", "System.UIntPtr", uintMaxValue, "0"); binaryOperator("System.UIntPtr", "&", "System.UIntPtr", intMaxValue, "System.UIntPtr", uintMaxValue, intMaxValue); binaryOperator("System.UIntPtr", "&", "System.UIntPtr", intMaxValue, "System.UIntPtr", "2147483648", "0"); binaryOperator("System.IntPtr", "|", "System.IntPtr", intMinValue, "System.IntPtr", "0", intMinValue); binaryOperator("System.IntPtr", "|", "System.IntPtr", intMinValue, "System.IntPtr", "-1", "-1"); binaryOperator("System.IntPtr", "|", "System.IntPtr", intMaxValue, "System.IntPtr", intMaxValue, intMaxValue); binaryOperator("System.UIntPtr", "|", "System.UIntPtr", "0", "System.UIntPtr", uintMaxValue, uintMaxValue); binaryOperator("System.UIntPtr", "|", "System.UIntPtr", intMaxValue, "System.UIntPtr", intMaxValue, intMaxValue); binaryOperator("System.UIntPtr", "|", "System.UIntPtr", intMaxValue, "System.UIntPtr", "2147483648", uintMaxValue); binaryOperator("System.IntPtr", "^", "System.IntPtr", intMinValue, "System.IntPtr", "0", intMinValue); binaryOperator("System.IntPtr", "^", "System.IntPtr", intMinValue, "System.IntPtr", "-1", intMaxValue); binaryOperator("System.IntPtr", "^", "System.IntPtr", intMaxValue, "System.IntPtr", intMaxValue, "0"); binaryOperator("System.UIntPtr", "^", "System.UIntPtr", "0", "System.UIntPtr", uintMaxValue, uintMaxValue); binaryOperator("System.UIntPtr", "^", "System.UIntPtr", intMaxValue, "System.UIntPtr", intMaxValue, "0"); binaryOperator("System.UIntPtr", "^", "System.UIntPtr", intMaxValue, "System.UIntPtr", "2147483648", uintMaxValue); static DiagnosticDescription[] getNoDiagnostics(string opType, string op, string operand) => Array.Empty<DiagnosticDescription>(); static DiagnosticDescription[] getBadUnaryOpDiagnostics(string opType, string op, string operand) => new[] { Diagnostic(ErrorCode.ERR_BadUnaryOp, operand).WithArguments(op, AsNative(opType)) }; static DiagnosticDescription[] getIntDivByZeroDiagnostics(string opType, string op, string operand) => new[] { Diagnostic(ErrorCode.ERR_IntDivByZero, operand) }; void unaryOperator(string opType, string op, string operand, string expectedResult, Func<string, string, string, DiagnosticDescription[]> getDiagnostics = null) { getDiagnostics ??= getNoDiagnostics; var declarations = $"const {opType} A = {operand};"; var expr = $"{op}A"; var diagnostics = getDiagnostics(opType, op, expr); constantDeclaration(opType, declarations, expr, expectedResult, diagnostics); constantDeclaration(opType, declarations, $"checked({expr})", expectedResult, diagnostics); constantDeclaration(opType, declarations, $"unchecked({expr})", expectedResult, diagnostics); expr = $"{op}({opType})({operand})"; diagnostics = getDiagnostics(opType, op, expr); constantExpression(opType, expr, expectedResult, diagnostics); constantExpression(opType, $"checked({expr})", expectedResult, diagnostics); constantExpression(opType, $"unchecked({expr})", expectedResult, diagnostics); } void unaryOperatorCheckedOverflow(string opType, string op, string operand, string expectedResultUnchecked, string expectedResultChecked) { var declarations = $"const {opType} A = {operand};"; var expr = $"{op}A"; constantDeclaration(opType, declarations, expr, null, new[] { Diagnostic(ErrorCode.WRN_CompileTimeCheckedOverflow, expr).WithArguments(AsNative( opType)), Diagnostic(ErrorCode.ERR_NotConstantExpression, expr).WithArguments("Library.F") }); constantDeclaration(opType, declarations, $"checked({expr})", null, new[] { Diagnostic(ErrorCode.WRN_CompileTimeCheckedOverflow, expr).WithArguments(AsNative(opType)), Diagnostic(ErrorCode.ERR_NotConstantExpression, $"checked({expr})").WithArguments("Library.F") }); constantDeclaration(opType, declarations, $"unchecked({expr})", null, new[] { Diagnostic(ErrorCode.ERR_NotConstantExpression, $"unchecked({expr})").WithArguments("Library.F") }); expr = $"{op}({opType})({operand})"; constantExpression(opType, expr, expectedResultUnchecked, new[] { Diagnostic(ErrorCode.WRN_CompileTimeCheckedOverflow, expr).WithArguments(AsNative(opType)) }); constantExpression(opType, $"checked({expr})", expectedResultChecked, new[] { Diagnostic(ErrorCode.WRN_CompileTimeCheckedOverflow, expr).WithArguments(AsNative(opType)) }); constantExpression(opType, $"unchecked({expr})", expectedResultUnchecked, Array.Empty<DiagnosticDescription>()); } void unaryOperatorNotConstant(string opType, string op, string operand, string expectedResult) { var declarations = $"const {opType} A = {operand};"; var expr = $"{op}A"; constantDeclaration(opType, declarations, expr, null, new[] { Diagnostic(ErrorCode.ERR_NotConstantExpression, expr).WithArguments("Library.F") }); constantDeclaration(opType, declarations, $"checked({expr})", null, new[] { Diagnostic(ErrorCode.ERR_NotConstantExpression, $"checked({expr})").WithArguments("Library.F") }); constantDeclaration(opType, declarations, $"unchecked({expr})", null, new[] { Diagnostic(ErrorCode.ERR_NotConstantExpression, $"unchecked({expr})").WithArguments("Library.F") }); expr = $"{op}({opType})({operand})"; constantExpression(opType, expr, expectedResult, Array.Empty<DiagnosticDescription>()); constantExpression(opType, $"checked({expr})", expectedResult, Array.Empty<DiagnosticDescription>()); constantExpression(opType, $"unchecked({expr})", expectedResult, Array.Empty<DiagnosticDescription>()); } void binaryOperator(string opType, string op, string leftType, string leftOperand, string rightType, string rightOperand, string expectedResult, Func<string, string, string, DiagnosticDescription[]> getDiagnostics = null) { getDiagnostics ??= getNoDiagnostics; var declarations = $"const {leftType} A = {leftOperand}; const {rightType} B = {rightOperand};"; var expr = $"A {op} B"; var diagnostics = getDiagnostics(opType, op, expr); constantDeclaration(opType, declarations, expr, expectedResult, diagnostics); constantDeclaration(opType, declarations, $"checked({expr})", expectedResult, diagnostics); constantDeclaration(opType, declarations, $"unchecked({expr})", expectedResult, diagnostics); expr = $"(({leftType})({leftOperand})) {op} (({rightType})({rightOperand}))"; diagnostics = getDiagnostics(opType, op, expr); constantExpression(opType, expr, expectedResult, diagnostics); constantExpression(opType, $"checked({expr})", expectedResult, diagnostics); constantExpression(opType, $"unchecked({expr})", expectedResult, diagnostics); } void binaryOperatorCheckedOverflow(string opType, string op, string leftType, string leftOperand, string rightType, string rightOperand, string expectedResultUnchecked, string expectedResultChecked) { var declarations = $"const {leftType} A = {leftOperand}; const {rightType} B = {rightOperand};"; var expr = $"A {op} B"; constantDeclaration(opType, declarations, expr, null, new[] { Diagnostic(ErrorCode.WRN_CompileTimeCheckedOverflow, expr).WithArguments(AsNative(opType)), Diagnostic(ErrorCode.ERR_NotConstantExpression, expr).WithArguments("Library.F") }); constantDeclaration(opType, declarations, $"checked({expr})", null, new[] { Diagnostic(ErrorCode.WRN_CompileTimeCheckedOverflow, expr).WithArguments(AsNative(opType)), Diagnostic(ErrorCode.ERR_NotConstantExpression, $"checked({expr})").WithArguments("Library.F") }); constantDeclaration(opType, declarations, $"unchecked({expr})", null, new[] { Diagnostic(ErrorCode.ERR_NotConstantExpression, $"unchecked({expr})").WithArguments("Library.F") }); expr = $"(({leftType})({leftOperand})) {op} (({rightType})({rightOperand}))"; constantExpression(opType, expr, expectedResultUnchecked, new[] { Diagnostic(ErrorCode.WRN_CompileTimeCheckedOverflow, expr).WithArguments(AsNative(opType)) }); constantExpression(opType, $"checked({expr})", expectedResultChecked, new[] { Diagnostic(ErrorCode.WRN_CompileTimeCheckedOverflow, expr).WithArguments(AsNative(opType)) }); constantExpression(opType, $"unchecked({expr})", expectedResultUnchecked, Array.Empty<DiagnosticDescription>()); } void binaryOperatorNotConstant(string opType, string op, string leftType, string leftOperand, string rightType, string rightOperand, string expectedResult) { var declarations = $"const {leftType} A = {leftOperand}; const {rightType} B = {rightOperand};"; var expr = $"A {op} B"; constantDeclaration(opType, declarations, expr, null, new[] { Diagnostic(ErrorCode.ERR_NotConstantExpression, expr).WithArguments("Library.F") }); constantDeclaration(opType, declarations, $"checked({expr})", null, new[] { Diagnostic(ErrorCode.ERR_NotConstantExpression, $"checked({expr})").WithArguments("Library.F") }); constantDeclaration(opType, declarations, $"unchecked({expr})", null, new[] { Diagnostic(ErrorCode.ERR_NotConstantExpression, $"unchecked({expr})").WithArguments("Library.F") }); expr = $"(({leftType})({leftOperand})) {op} (({rightType})({rightOperand}))"; constantExpression(opType, expr, expectedResult, Array.Empty<DiagnosticDescription>()); constantExpression(opType, $"checked({expr})", expectedResult, Array.Empty<DiagnosticDescription>()); constantExpression(opType, $"unchecked({expr})", expectedResult, Array.Empty<DiagnosticDescription>()); } void constantDeclaration(string opType, string declarations, string expr, string expectedResult, DiagnosticDescription[] expectedDiagnostics) { string sourceA = $@"public class Library {{ {declarations} public const {opType} F = {expr}; }}"; var parseOptions = expr.Contains(">>>", StringComparison.Ordinal) ? TestOptions.Regular11 : TestOptions.Regular9; var comp = CreateCompilation(sourceA, parseOptions: parseOptions, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(expectedDiagnostics); if (expectedDiagnostics.Any(d => ErrorFacts.GetSeverity((ErrorCode)d.Code) == DiagnosticSeverity.Error)) { Assert.Null(expectedResult); return; } string sourceB = @"class Program { static void Main() { System.Console.WriteLine(Library.F); } }"; var refA = comp.EmitToImageReference(); comp = CreateCompilation(sourceB, references: new[] { refA }, options: TestOptions.ReleaseExe, parseOptions: parseOptions, targetFramework: TargetFramework.Net70); // Investigating flaky IL verification issue. Tracked by https://github.com/dotnet/roslyn/issues/63782 CompileAndVerify(comp, verify: new Verification() { Status = VerificationStatus.PassesOrFailFast | VerificationStatus.FailsPEVerify }, expectedOutput: IncludeExpectedOutput(expectedResult)); Assert.NotNull(expectedResult); } void constantExpression(string opType, string expr, string expectedResult, DiagnosticDescription[] expectedDiagnostics) { string source = $@"using System; class Program {{ static void Main() {{ object result; try {{ {opType} value = {expr}; result = value; }} catch (Exception e) {{ result = e.GetType().FullName; }} Console.WriteLine(result); }} }}"; var parseOptions = expr.Contains(">>>", StringComparison.Ordinal) ? TestOptions.Regular11 : TestOptions.Regular9; var comp = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: parseOptions, targetFramework: TargetFramework.Net70); if (expectedDiagnostics.Any(d => ErrorFacts.GetSeverity((ErrorCode)d.Code) == DiagnosticSeverity.Error)) { comp.VerifyDiagnostics(expectedDiagnostics); Assert.Null(expectedResult); return; } // Investigating flaky IL verification issue. Tracked by https://github.com/dotnet/roslyn/issues/63782 CompileAndVerify(comp, verify: new Verification() { Status = VerificationStatus.FailsPEVerify | VerificationStatus.PassesOrFailFast }, expectedOutput: IncludeExpectedOutput(expectedResult)).VerifyDiagnostics(expectedDiagnostics); Assert.NotNull(expectedResult); } } [Fact] public void ConstantFolding_02() { var source = @" using System; class Program { static void Main() { const UIntPtr x = unchecked(uint.MaxValue + (UIntPtr)42); const UIntPtr y = checked(uint.MaxValue + (UIntPtr)42); } }"; var comp = CreateCompilation(source, options: TestOptions.ReleaseExe, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics( // (8,27): error CS0133: The expression being assigned to 'x' must be constant // const UIntPtr x = unchecked(uint.MaxValue + (UIntPtr)42); Diagnostic(ErrorCode.ERR_NotConstantExpression, "unchecked(uint.MaxValue + (UIntPtr)42)").WithArguments("x").WithLocation(8, 27), // (9,27): error CS0133: The expression being assigned to 'y' must be constant // const UIntPtr y = checked(uint.MaxValue + (UIntPtr)42); Diagnostic(ErrorCode.ERR_NotConstantExpression, "checked(uint.MaxValue + (UIntPtr)42)").WithArguments("y").WithLocation(9, 27), // (9,35): warning CS8973: The operation may overflow 'nuint' at runtime (use 'unchecked' syntax to override) // const UIntPtr y = checked(uint.MaxValue + (UIntPtr)42); Diagnostic(ErrorCode.WRN_CompileTimeCheckedOverflow, "uint.MaxValue + (UIntPtr)42").WithArguments("nuint").WithLocation(9, 35) ); source = @" using System; class Program { static void Main() { try { var y = checked(uint.MaxValue + (UIntPtr)42); System.Console.WriteLine(y); } catch (System.Exception e) { System.Console.WriteLine(e.GetType()); } } }"; comp = CreateCompilation(source, options: TestOptions.ReleaseExe, targetFramework: TargetFramework.Net70); CompileAndVerify(comp, verify: Verification.FailsPEVerify, expectedOutput: IncludeExpectedOutput(IntPtr.Size == 4 ? "System.OverflowException" : "4294967337")).VerifyDiagnostics( // (10,29): warning CS8973: The operation may overflow 'nuint' at runtime (use 'unchecked' syntax to override) // var y = checked(uint.MaxValue + (UIntPtr)42); Diagnostic(ErrorCode.WRN_CompileTimeCheckedOverflow, "uint.MaxValue + (UIntPtr)42").WithArguments("nuint").WithLocation(10, 29) ); source = @" using System; class Program { static void Main() { var y = unchecked(uint.MaxValue + (UIntPtr)42); System.Console.WriteLine(y); } }"; comp = CreateCompilation(source, options: TestOptions.ReleaseExe, targetFramework: TargetFramework.Net70); CompileAndVerify(comp, verify: Verification.FailsPEVerify, expectedOutput: IncludeExpectedOutput(IntPtr.Size == 4 ? "41" : "4294967337")).VerifyDiagnostics(); } [Fact] public void ConstantFolding_03() { var source = @" using System; class Program { static void Main() { const IntPtr x = unchecked(-(IntPtr)int.MinValue); const IntPtr y = checked(-(IntPtr)int.MinValue); } }"; var comp = CreateCompilation(source, options: TestOptions.ReleaseExe, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics( // (8,26): error CS0133: The expression being assigned to 'x' must be constant // const IntPtr x = unchecked(-(IntPtr)int.MinValue); Diagnostic(ErrorCode.ERR_NotConstantExpression, "unchecked(-(IntPtr)int.MinValue)").WithArguments("x").WithLocation(8, 26), // (9,26): error CS0133: The expression being assigned to 'y' must be constant // const IntPtr y = checked(-(IntPtr)int.MinValue); Diagnostic(ErrorCode.ERR_NotConstantExpression, "checked(-(IntPtr)int.MinValue)").WithArguments("y").WithLocation(9, 26), // (9,34): warning CS8973: The operation may overflow 'nint' at runtime (use 'unchecked' syntax to override) // const IntPtr y = checked(-(IntPtr)int.MinValue); Diagnostic(ErrorCode.WRN_CompileTimeCheckedOverflow, "-(IntPtr)int.MinValue").WithArguments("nint").WithLocation(9, 34) ); source = @" using System; class Program { static void Main() { try { var y = checked(-(IntPtr)int.MinValue); System.Console.WriteLine(y); } catch (System.Exception e) { System.Console.WriteLine(e.GetType()); } } }"; comp = CreateCompilation(source, options: TestOptions.ReleaseExe, targetFramework: TargetFramework.Net70); CompileAndVerify(comp, verify: Verification.FailsPEVerify, expectedOutput: IncludeExpectedOutput(IntPtr.Size == 4 ? "System.OverflowException" : "2147483648")).VerifyDiagnostics( // (10,29): warning CS8973: The operation may overflow 'nint' at runtime (use 'unchecked' syntax to override) // var y = checked(-(IntPtr)int.MinValue); Diagnostic(ErrorCode.WRN_CompileTimeCheckedOverflow, "-(IntPtr)int.MinValue").WithArguments("nint").WithLocation(10, 29) ); source = @" using System; class Program { static void Main() { var y = unchecked(-(IntPtr)int.MinValue); System.Console.WriteLine(y); } }"; comp = CreateCompilation(source, options: TestOptions.ReleaseExe, targetFramework: TargetFramework.Net70); CompileAndVerify(comp, verify: Verification.FailsPEVerify, expectedOutput: IncludeExpectedOutput(IntPtr.Size == 4 ? "-2147483648" : "2147483648")).VerifyDiagnostics(); } // OverflowException behavior is consistent with unchecked int division. [Fact] public void UncheckedIntegerDivision() { string source = @"using System; class Program { static void Main() { Console.WriteLine(Execute(() => IntDivision(int.MinValue + 1, -1))); Console.WriteLine(Execute(() => IntDivision(int.MinValue, -1))); Console.WriteLine(Execute(() => IntRemainder(int.MinValue + 1, -1))); Console.WriteLine(Execute(() => IntRemainder(int.MinValue, -1))); Console.WriteLine(Execute(() => NativeIntDivision(int.MinValue + 1, -1))); Console.WriteLine(Execute(() => NativeIntDivision(int.MinValue, -1))); Console.WriteLine(Execute(() => NativeIntRemainder(int.MinValue + 1, -1))); Console.WriteLine(Execute(() => NativeIntRemainder(int.MinValue, -1))); } static object Execute(Func<object> f) { try { return f(); } catch (Exception e) { return e.GetType().FullName; } } static int IntDivision(int x, int y) => unchecked(x / y); static int IntRemainder(int x, int y) => unchecked(x % y); static nint NativeIntDivision(IntPtr x, IntPtr y) => unchecked(x / y); static nint NativeIntRemainder(IntPtr x, IntPtr y) => unchecked(x % y); }"; var comp = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); CompileAndVerify(comp, verify: Verification.FailsPEVerify, expectedOutput: IncludeExpectedOutput( $@"2147483647 System.OverflowException 0 System.OverflowException 2147483647 {(IntPtr.Size == 4 ? "System.OverflowException" : "2147483648")} 0 {(IntPtr.Size == 4 ? "System.OverflowException" : "0")}")); } [Fact] public void UncheckedLeftShift_01() { string source = @"using System; class Program { static void Main() { const nint x = 0x7fffffff; Report(x << 1); Report(LeftShift(x, 1)); } static nint LeftShift(nint x, int y) => unchecked(x << y); static void Report(long l) => Console.WriteLine(""{0:x}"", l); }"; var comp = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); var expectedValue = IntPtr.Size == 4 ? "fffffffffffffffe" : "fffffffe"; CompileAndVerify(comp, verify: Verification.FailsPEVerify, expectedOutput: IncludeExpectedOutput( $@"{expectedValue} {expectedValue}")); } [Fact] public void UncheckedLeftShift_02() { string source = @"using System; class Program { static void Main() { const nuint x = 0xffffffff; Report(x << 1); Report(LeftShift(x, 1)); } static nuint LeftShift(nuint x, int y) => unchecked(x << y); static void Report(ulong u) => Console.WriteLine(""{0:x}"", u); }"; var comp = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); var expectedValue = IntPtr.Size == 4 ? "fffffffe" : "1fffffffe"; CompileAndVerify(comp, verify: Verification.FailsPEVerify, expectedOutput: IncludeExpectedOutput( $@"{expectedValue} {expectedValue}")); } [Fact] public void ExplicitImplementationReturnTypeDifferences() { string source = @"struct S<T> { } interface I { S<nint> F1(); S<System.IntPtr> F2(); S<nint> F3(); S<System.IntPtr> F4(); } class C : I { S<System.IntPtr> I.F1() => default; S<nint> I.F2() => default; S<nint> I.F3() => default; S<System.IntPtr> I.F4() => default; }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics(); var type = comp.GetTypeByMetadataName("I"); Assert.Equal("S<nint> I.F1()", type.GetMember("F1").ToDisplayString(TestFormat)); Assert.Equal("S<nint> I.F2()", type.GetMember("F2").ToDisplayString(TestFormat)); Assert.Equal("S<nint> I.F3()", type.GetMember("F3").ToDisplayString(TestFormat)); Assert.Equal("S<nint> I.F4()", type.GetMember("F4").ToDisplayString(TestFormat)); type = comp.GetTypeByMetadataName("C"); Assert.Equal("S<nint> C.I.F1()", type.GetMember("I.F1").ToDisplayString(TestFormat)); Assert.Equal("S<nint> C.I.F2()", type.GetMember("I.F2").ToDisplayString(TestFormat)); Assert.Equal("S<nint> C.I.F3()", type.GetMember("I.F3").ToDisplayString(TestFormat)); Assert.Equal("S<nint> C.I.F4()", type.GetMember("I.F4").ToDisplayString(TestFormat)); } [Fact] public void OverrideReturnTypeDifferences() { string source = @"class A { public virtual nint[] F1() => null; public virtual System.IntPtr[] F2() => null; public virtual nint[] F3() => null; public virtual System.IntPtr[] F4() => null; } class B : A { public override System.IntPtr[] F1() => null; public override nint[] F2() => null; public override nint[] F3() => null; public override System.IntPtr[] F4() => null; }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyEmitDiagnostics(); var type = comp.GetTypeByMetadataName("A"); Assert.Equal("nint[] A.F1()", type.GetMember("F1").ToDisplayString(TestFormat)); Assert.Equal("nint[] A.F2()", type.GetMember("F2").ToDisplayString(TestFormat)); Assert.Equal("nint[] A.F3()", type.GetMember("F3").ToDisplayString(TestFormat)); Assert.Equal("nint[] A.F4()", type.GetMember("F4").ToDisplayString(TestFormat)); type = comp.GetTypeByMetadataName("B"); Assert.Equal("nint[] B.F1()", type.GetMember("F1").ToDisplayString(TestFormat)); Assert.Equal("nint[] B.F2()", type.GetMember("F2").ToDisplayString(TestFormat)); Assert.Equal("nint[] B.F3()", type.GetMember("F3").ToDisplayString(TestFormat)); Assert.Equal("nint[] B.F4()", type.GetMember("F4").ToDisplayString(TestFormat)); } [Fact] public void Int64Conversions() { convert(fromType: "nint", toType: "ulong", "int.MinValue", "18446744071562067968", "conv.i8", "System.OverflowException", "conv.ovf.u8"); convert(fromType: "nint", toType: "ulong", "int.MaxValue", "2147483647", "conv.i8", "2147483647", "conv.ovf.u8"); convert(fromType: "nint", toType: "nuint", "int.MinValue", IntPtr.Size == 4 ? "2147483648" : "18446744071562067968", null, "System.OverflowException", "conv.ovf.u"); convert(fromType: "nint", toType: "nuint", "int.MaxValue", "2147483647", null, "2147483647", "conv.ovf.u"); convert(fromType: "nuint", toType: "long", "uint.MaxValue", "4294967295", "conv.u8", "4294967295", "conv.ovf.i8.un"); convert(fromType: "nuint", toType: "nint", "uint.MaxValue", IntPtr.Size == 4 ? "-1" : "4294967295", null, IntPtr.Size == 4 ? "System.OverflowException" : "4294967295", "conv.ovf.i.un"); string nintMinValue = IntPtr.Size == 4 ? int.MinValue.ToString() : long.MinValue.ToString(); string nintMaxValue = IntPtr.Size == 4 ? int.MaxValue.ToString() : long.MaxValue.ToString(); string nuintMaxValue = IntPtr.Size == 4 ? uint.MaxValue.ToString() : ulong.MaxValue.ToString(); convert(fromType: "nint", toType: "ulong", nintMinValue, IntPtr.Size == 4 ? "18446744071562067968" : "9223372036854775808", "conv.i8", "System.OverflowException", "conv.ovf.u8"); convert(fromType: "nint", toType: "ulong", nintMaxValue, IntPtr.Size == 4 ? "2147483647" : "9223372036854775807", "conv.i8", IntPtr.Size == 4 ? "2147483647" : "9223372036854775807", "conv.ovf.u8"); convert(fromType: "nint", toType: "nuint", nintMinValue, IntPtr.Size == 4 ? "2147483648" : "9223372036854775808", null, "System.OverflowException", "conv.ovf.u"); convert(fromType: "nint", toType: "nuint", nintMaxValue, IntPtr.Size == 4 ? "2147483647" : "9223372036854775807", null, IntPtr.Size == 4 ? "2147483647" : "9223372036854775807", "conv.ovf.u"); convert(fromType: "nuint", toType: "long", nuintMaxValue, IntPtr.Size == 4 ? "4294967295" : "-1", "conv.u8", IntPtr.Size == 4 ? "4294967295" : "System.OverflowException", "conv.ovf.i8.un"); convert(fromType: "nuint", toType: "nint", nuintMaxValue, "-1", null, "System.OverflowException", "conv.ovf.i.un"); void convert(string fromType, string toType, string fromValue, string toValueUnchecked, string toConvUnchecked, string toValueChecked, string toConvChecked) { string source = $@"using System; class Program {{ static {toType} Convert({fromType} value) => ({toType})(value); static {toType} ConvertChecked({fromType} value) => checked(({toType})(value)); static object Execute(Func<object> f) {{ try {{ return f(); }} catch (Exception e) {{ return e.GetType().FullName; }} }} static void Main() {{ {fromType} value = ({fromType})({fromValue}); Console.WriteLine(Execute(() => Convert(value))); Console.WriteLine(Execute(() => ConvertChecked(value))); }} }}"; var comp = CreateCompilation(source, options: TestOptions.UnsafeReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); var verifier = CompileAndVerify(comp, verify: Verification.FailsPEVerify, expectedOutput: IncludeExpectedOutput( $@"{toValueUnchecked} {toValueChecked}")); verifier.VerifyIL("Program.Convert", toConvUnchecked is null ? @" { // Code size 2 (0x2) .maxstack 1 IL_0000: ldarg.0 IL_0001: ret }" : $@"{{ // Code size 3 (0x3) .maxstack 1 IL_0000: ldarg.0 IL_0001: {toConvUnchecked} IL_0002: ret }}"); verifier.VerifyIL("Program.ConvertChecked", $@"{{ // Code size 3 (0x3) .maxstack 1 IL_0000: ldarg.0 IL_0001: {toConvChecked} IL_0002: ret }}"); } } [Theory] [InlineData("void*")] [InlineData("byte*")] [InlineData("delegate*<void>")] public void PointerConversions(string pointerType) { string source = $@"using System; unsafe class Program {{ static {pointerType} ToPointer1(nint i) => ({pointerType})i; static {pointerType} ToPointer2(nuint u) => ({pointerType})u; static {pointerType} ToPointer3(nint i) => checked(({pointerType})i); static {pointerType} ToPointer4(nuint u) => checked(({pointerType})u); static nint FromPointer1({pointerType} p) => (nint)p; static nuint FromPointer2({pointerType} p) => (nuint)p; static nint FromPointer3({pointerType} p) => checked((nint)p); static nuint FromPointer4({pointerType} p) => checked((nuint)p); static object Execute(Func<object> f) {{ try {{ return f(); }} catch (Exception e) {{ return e.GetType().FullName; }} }} static void Execute({pointerType} p) {{ Console.WriteLine((int)p); Console.WriteLine(Execute(() => FromPointer1(p))); Console.WriteLine(Execute(() => FromPointer2(p))); Console.WriteLine(Execute(() => FromPointer3(p))); Console.WriteLine(Execute(() => FromPointer4(p))); }} static void Main() {{ Execute(ToPointer1(-42)); Execute(ToPointer2(42)); Execute(ToPointer1(int.MinValue)); Execute(ToPointer2(uint.MaxValue)); Console.WriteLine(Execute(() => (ulong)ToPointer3(-42))); Console.WriteLine(Execute(() => (ulong)ToPointer4(42))); Console.WriteLine(Execute(() => (ulong)ToPointer3(int.MinValue))); Console.WriteLine(Execute(() => (ulong)ToPointer4(uint.MaxValue))); }} }}"; var comp = CreateCompilation(source, options: TestOptions.UnsafeReleaseExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); string expectedOutput = $@"-42 -42 {(IntPtr.Size == 4 ? "4294967254" : "18446744073709551574")} System.OverflowException {(IntPtr.Size == 4 ? "4294967254" : "18446744073709551574")} 42 42 42 42 42 -2147483648 -2147483648 {(IntPtr.Size == 4 ? "2147483648" : "18446744071562067968")} System.OverflowException {(IntPtr.Size == 4 ? "2147483648" : "18446744071562067968")} -1 {(IntPtr.Size == 4 ? "-1" : "4294967295")} 4294967295 {(IntPtr.Size == 4 ? "System.OverflowException" : "4294967295")} 4294967295 System.OverflowException 42 System.OverflowException 4294967295"; var verifier = CompileAndVerify(comp, verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput(expectedOutput)); verifier.VerifyIL("Program.ToPointer1", @"{ // Code size 2 (0x2) .maxstack 1 IL_0000: ldarg.0 IL_0001: ret }"); verifier.VerifyIL("Program.ToPointer2", @"{ // Code size 2 (0x2) .maxstack 1 IL_0000: ldarg.0 IL_0001: ret }"); verifier.VerifyIL("Program.ToPointer3", @"{ // Code size 3 (0x3) .maxstack 1 IL_0000: ldarg.0 IL_0001: conv.ovf.u IL_0002: ret }"); verifier.VerifyIL("Program.ToPointer4", @"{ // Code size 2 (0x2) .maxstack 1 IL_0000: ldarg.0 IL_0001: ret }"); verifier.VerifyIL("Program.FromPointer1", @"{ // Code size 2 (0x2) .maxstack 1 IL_0000: ldarg.0 IL_0001: ret }"); verifier.VerifyIL("Program.FromPointer2", @"{ // Code size 2 (0x2) .maxstack 1 IL_0000: ldarg.0 IL_0001: ret }"); verifier.VerifyIL("Program.FromPointer3", @"{ // Code size 3 (0x3) .maxstack 1 IL_0000: ldarg.0 IL_0001: conv.ovf.i.un IL_0002: ret }"); verifier.VerifyIL("Program.FromPointer4", @"{ // Code size 2 (0x2) .maxstack 1 IL_0000: ldarg.0 IL_0001: ret }"); } [Theory] [InlineData(null)] [InlineData("sbyte")] [InlineData("byte")] [InlineData("short")] [InlineData("ushort")] [InlineData("int")] [InlineData("uint")] [InlineData("long")] [InlineData("ulong")] public void EnumConversions_01(string baseType) { if (baseType != null) baseType = " : " + baseType; string sourceA = $@"enum E{baseType} {{ A = 0, B = 1 }}"; string sourceB = @"#pragma warning disable 219 class Program { static void F1() { E e; const nint i0 = 0; const nint i1 = 1; e = i0; e = i1; } static void F2() { E e; const nuint u0 = 0; const nuint u1 = 1; e = u0; e = u1; } static void F3() { nint i; i = default(E); i = E.A; i = E.B; } static void F4() { nuint u; u = default(E); u = E.A; u = E.B; } }"; var comp = CreateCompilation(new[] { sourceA, sourceB }, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics( // (10,13): error CS0266: Cannot implicitly convert type 'nint' to 'E'. An explicit conversion exists (are you missing a cast?) // e = i1; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "i1").WithArguments("nint", "E").WithLocation(10, 13), // (18,13): error CS0266: Cannot implicitly convert type 'nuint' to 'E'. An explicit conversion exists (are you missing a cast?) // e = u1; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "u1").WithArguments("nuint", "E").WithLocation(18, 13), // (23,13): error CS0266: Cannot implicitly convert type 'E' to 'nint'. An explicit conversion exists (are you missing a cast?) // i = default(E); Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "default(E)").WithArguments("E", "nint").WithLocation(23, 13), // (24,13): error CS0266: Cannot implicitly convert type 'E' to 'nint'. An explicit conversion exists (are you missing a cast?) // i = E.A; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "E.A").WithArguments("E", "nint").WithLocation(24, 13), // (25,13): error CS0266: Cannot implicitly convert type 'E' to 'nint'. An explicit conversion exists (are you missing a cast?) // i = E.B; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "E.B").WithArguments("E", "nint").WithLocation(25, 13), // (30,13): error CS0266: Cannot implicitly convert type 'E' to 'nuint'. An explicit conversion exists (are you missing a cast?) // u = default(E); Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "default(E)").WithArguments("E", "nuint").WithLocation(30, 13), // (31,13): error CS0266: Cannot implicitly convert type 'E' to 'nuint'. An explicit conversion exists (are you missing a cast?) // u = E.A; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "E.A").WithArguments("E", "nuint").WithLocation(31, 13), // (32,13): error CS0266: Cannot implicitly convert type 'E' to 'nuint'. An explicit conversion exists (are you missing a cast?) // u = E.B; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "E.B").WithArguments("E", "nuint").WithLocation(32, 13)); } [Theory] [InlineData(null)] [InlineData("sbyte")] [InlineData("short")] [InlineData("int")] [InlineData("long")] public void EnumConversions_02(string baseType) { if (baseType != null) baseType = " : " + baseType; string sourceA = $@"enum E{baseType} {{ A = -1, B = 1 }}"; string sourceB = @"using static System.Console; class Program { static E F1(nint i) => (E)i; static E F2(nuint u) => (E)u; static nint F3(E e) => (nint)e; static nuint F4(E e) => (nuint)e; static void Main() { WriteLine(F1(-1)); WriteLine(F2(1)); WriteLine(F3(E.A)); WriteLine(F4(E.B)); } }"; var comp = CreateCompilation(new[] { sourceA, sourceB }, parseOptions: TestOptions.Regular9, options: TestOptions.ReleaseExe, targetFramework: TargetFramework.Net70); CompileAndVerify(comp, verify: Verification.FailsPEVerify, expectedOutput: IncludeExpectedOutput( @"A B -1 1")); } [Fact] public void EnumConversions_03() { convert(baseType: null, fromType: "E", toType: "nint", "int.MinValue", "-2147483648", "conv.i", "-2147483648", "conv.i"); convert(baseType: null, fromType: "E", toType: "nint", "int.MaxValue", "2147483647", "conv.i", "2147483647", "conv.i"); convert(baseType: null, fromType: "E", toType: "nuint", "int.MinValue", IntPtr.Size == 4 ? "2147483648" : "18446744071562067968", "conv.i", "System.OverflowException", "conv.ovf.u"); convert(baseType: null, fromType: "E", toType: "nuint", "int.MaxValue", "2147483647", "conv.i", "2147483647", "conv.ovf.u"); convert(baseType: null, fromType: "nint", toType: "E", "int.MinValue", "-2147483648", "conv.i4", "-2147483648", "conv.ovf.i4"); convert(baseType: null, fromType: "nint", toType: "E", "int.MaxValue", "2147483647", "conv.i4", "2147483647", "conv.ovf.i4"); convert(baseType: null, fromType: "nuint", toType: "E", "uint.MaxValue", "-1", "conv.i4", "System.OverflowException", "conv.ovf.i4.un"); convert(baseType: null, fromType: "System.IntPtr", toType: "E", "int.MinValue", "-2147483648", "conv.i4", "-2147483648", "conv.ovf.i4"); convert(baseType: null, fromType: "System.IntPtr", toType: "E", "int.MaxValue", "2147483647", "conv.i4", "2147483647", "conv.ovf.i4"); convert(baseType: null, fromType: "System.UIntPtr", toType: "E", "uint.MaxValue", "-1", "conv.i4", "System.OverflowException", "conv.ovf.i4.un"); convert(baseType: "sbyte", fromType: "E", toType: "nint", "sbyte.MinValue", "-128", "conv.i", "-128", "conv.i"); convert(baseType: "sbyte", fromType: "E", toType: "nint", "sbyte.MaxValue", "127", "conv.i", "127", "conv.i"); convert(baseType: "sbyte", fromType: "E", toType: "nuint", "sbyte.MinValue", IntPtr.Size == 4 ? "4294967168" : "18446744073709551488", "conv.i", "System.OverflowException", "conv.ovf.u"); convert(baseType: "sbyte", fromType: "E", toType: "nuint", "sbyte.MaxValue", "127", "conv.i", "127", "conv.ovf.u"); convert(baseType: "sbyte", fromType: "nint", toType: "E", "int.MinValue", "A", "conv.i1", "System.OverflowException", "conv.ovf.i1"); convert(baseType: "sbyte", fromType: "nint", toType: "E", "int.MaxValue", "-1", "conv.i1", "System.OverflowException", "conv.ovf.i1"); convert(baseType: "sbyte", fromType: "nuint", toType: "E", "uint.MaxValue", "-1", "conv.i1", "System.OverflowException", "conv.ovf.i1.un"); convert(baseType: "sbyte", fromType: "System.IntPtr", toType: "E", "int.MinValue", "A", "conv.i1", "System.OverflowException", "conv.ovf.i1"); convert(baseType: "sbyte", fromType: "System.IntPtr", toType: "E", "int.MaxValue", "-1", "conv.i1", "System.OverflowException", "conv.ovf.i1"); convert(baseType: "sbyte", fromType: "System.UIntPtr", toType: "E", "uint.MaxValue", "-1", "conv.i1", "System.OverflowException", "conv.ovf.i1.un"); convert(baseType: "byte", fromType: "E", toType: "nint", "byte.MaxValue", "255", "conv.u", "255", "conv.u"); convert(baseType: "byte", fromType: "E", toType: "nuint", "byte.MaxValue", "255", "conv.u", "255", "conv.u"); convert(baseType: "byte", fromType: "nint", toType: "E", "int.MinValue", "A", "conv.u1", "System.OverflowException", "conv.ovf.u1"); convert(baseType: "byte", fromType: "nint", toType: "E", "int.MaxValue", "255", "conv.u1", "System.OverflowException", "conv.ovf.u1"); convert(baseType: "byte", fromType: "nuint", toType: "E", "uint.MaxValue", "255", "conv.u1", "System.OverflowException", "conv.ovf.u1.un"); convert(baseType: "byte", fromType: "System.IntPtr", toType: "E", "int.MinValue", "A", "conv.u1", "System.OverflowException", "conv.ovf.u1"); convert(baseType: "byte", fromType: "System.IntPtr", toType: "E", "int.MaxValue", "255", "conv.u1", "System.OverflowException", "conv.ovf.u1"); convert(baseType: "byte", fromType: "System.UIntPtr", toType: "E", "uint.MaxValue", "255", "conv.u1", "System.OverflowException", "conv.ovf.u1.un"); convert(baseType: "short", fromType: "E", toType: "nint", "short.MinValue", "-32768", "conv.i", "-32768", "conv.i"); convert(baseType: "short", fromType: "E", toType: "nint", "short.MaxValue", "32767", "conv.i", "32767", "conv.i"); convert(baseType: "short", fromType: "E", toType: "nuint", "short.MinValue", IntPtr.Size == 4 ? "4294934528" : "18446744073709518848", "conv.i", "System.OverflowException", "conv.ovf.u"); convert(baseType: "short", fromType: "E", toType: "nuint", "short.MaxValue", "32767", "conv.i", "32767", "conv.ovf.u"); convert(baseType: "short", fromType: "nint", toType: "E", "int.MinValue", "A", "conv.i2", "System.OverflowException", "conv.ovf.i2"); convert(baseType: "short", fromType: "nint", toType: "E", "int.MaxValue", "-1", "conv.i2", "System.OverflowException", "conv.ovf.i2"); convert(baseType: "short", fromType: "nuint", toType: "E", "uint.MaxValue", "-1", "conv.i2", "System.OverflowException", "conv.ovf.i2.un"); convert(baseType: "short", fromType: "System.IntPtr", toType: "E", "int.MinValue", "A", "conv.i2", "System.OverflowException", "conv.ovf.i2"); convert(baseType: "short", fromType: "System.IntPtr", toType: "E", "int.MaxValue", "-1", "conv.i2", "System.OverflowException", "conv.ovf.i2"); convert(baseType: "short", fromType: "System.UIntPtr", toType: "E", "uint.MaxValue", "-1", "conv.i2", "System.OverflowException", "conv.ovf.i2.un"); convert(baseType: "ushort", fromType: "E", toType: "nint", "ushort.MaxValue", "65535", "conv.u", "65535", "conv.u"); convert(baseType: "ushort", fromType: "E", toType: "nuint", "ushort.MaxValue", "65535", "conv.u", "65535", "conv.u"); convert(baseType: "ushort", fromType: "nint", toType: "E", "int.MinValue", "A", "conv.u2", "System.OverflowException", "conv.ovf.u2"); convert(baseType: "ushort", fromType: "nint", toType: "E", "int.MaxValue", "65535", "conv.u2", "System.OverflowException", "conv.ovf.u2"); convert(baseType: "ushort", fromType: "nuint", toType: "E", "uint.MaxValue", "65535", "conv.u2", "System.OverflowException", "conv.ovf.u2.un"); convert(baseType: "ushort", fromType: "System.IntPtr", toType: "E", "int.MinValue", "A", "conv.u2", "System.OverflowException", "conv.ovf.u2"); convert(baseType: "ushort", fromType: "System.IntPtr", toType: "E", "int.MaxValue", "65535", "conv.u2", "System.OverflowException", "conv.ovf.u2"); convert(baseType: "ushort", fromType: "System.UIntPtr", toType: "E", "uint.MaxValue", "65535", "conv.u2", "System.OverflowException", "conv.ovf.u2.un"); convert(baseType: "int", fromType: "E", toType: "nint", "int.MinValue", "-2147483648", "conv.i", "-2147483648", "conv.i"); convert(baseType: "int", fromType: "E", toType: "nint", "int.MaxValue", "2147483647", "conv.i", "2147483647", "conv.i"); convert(baseType: "int", fromType: "E", toType: "nuint", "int.MinValue", IntPtr.Size == 4 ? "2147483648" : "18446744071562067968", "conv.i", "System.OverflowException", "conv.ovf.u"); convert(baseType: "int", fromType: "E", toType: "nuint", "int.MaxValue", "2147483647", "conv.i", "2147483647", "conv.ovf.u"); convert(baseType: "int", fromType: "nint", toType: "E", "int.MinValue", "-2147483648", "conv.i4", "-2147483648", "conv.ovf.i4"); convert(baseType: "int", fromType: "nint", toType: "E", "int.MaxValue", "2147483647", "conv.i4", "2147483647", "conv.ovf.i4"); convert(baseType: "int", fromType: "nuint", toType: "E", "uint.MaxValue", "-1", "conv.i4", "System.OverflowException", "conv.ovf.i4.un"); convert(baseType: "int", fromType: "System.IntPtr", toType: "E", "int.MinValue", "-2147483648", "conv.i4", "-2147483648", "conv.ovf.i4"); convert(baseType: "int", fromType: "System.IntPtr", toType: "E", "int.MaxValue", "2147483647", "conv.i4", "2147483647", "conv.ovf.i4"); convert(baseType: "int", fromType: "System.UIntPtr", toType: "E", "uint.MaxValue", "-1", "conv.i4", "System.OverflowException", "conv.ovf.i4.un"); convert(baseType: "uint", fromType: "E", toType: "nint", "uint.MaxValue", IntPtr.Size == 4 ? "-1" : "4294967295", "conv.u", IntPtr.Size == 4 ? "System.OverflowException" : "4294967295", "conv.ovf.i.un"); convert(baseType: "uint", fromType: "E", toType: "nuint", "uint.MaxValue", "4294967295", "conv.u", "4294967295", "conv.u"); convert(baseType: "uint", fromType: "nint", toType: "E", "int.MinValue", "2147483648", "conv.u4", "System.OverflowException", "conv.ovf.u4"); convert(baseType: "uint", fromType: "nint", toType: "E", "int.MaxValue", "2147483647", "conv.u4", "2147483647", "conv.ovf.u4"); convert(baseType: "uint", fromType: "nuint", toType: "E", "uint.MaxValue", "4294967295", "conv.u4", "4294967295", "conv.ovf.u4.un"); convert(baseType: "uint", fromType: "System.IntPtr", toType: "E", "int.MinValue", "2147483648", "conv.u4", "System.OverflowException", "conv.ovf.u4"); convert(baseType: "uint", fromType: "System.IntPtr", toType: "E", "int.MaxValue", "2147483647", "conv.u4", "2147483647", "conv.ovf.u4"); convert(baseType: "uint", fromType: "System.UIntPtr", toType: "E", "uint.MaxValue", "4294967295", "conv.u4", "4294967295", "conv.ovf.u4.un"); convert(baseType: "long", fromType: "E", toType: "nint", "long.MinValue", IntPtr.Size == 4 ? "0" : "-9223372036854775808", "conv.i", IntPtr.Size == 4 ? "System.OverflowException" : "-9223372036854775808", "conv.ovf.i"); convert(baseType: "long", fromType: "E", toType: "nint", "long.MaxValue", IntPtr.Size == 4 ? "-1" : "9223372036854775807", "conv.i", IntPtr.Size == 4 ? "System.OverflowException" : "9223372036854775807", "conv.ovf.i"); convert(baseType: "long", fromType: "E", toType: "nuint", "long.MinValue", IntPtr.Size == 4 ? "0" : "9223372036854775808", "conv.u", "System.OverflowException", "conv.ovf.u"); convert(baseType: "long", fromType: "E", toType: "nuint", "long.MaxValue", IntPtr.Size == 4 ? "4294967295" : "9223372036854775807", "conv.u", IntPtr.Size == 4 ? "System.OverflowException" : "9223372036854775807", "conv.ovf.u"); convert(baseType: "long", fromType: "nint", toType: "E", "int.MinValue", "-2147483648", "conv.i8", "-2147483648", "conv.i8"); convert(baseType: "long", fromType: "nint", toType: "E", "int.MaxValue", "2147483647", "conv.i8", "2147483647", "conv.i8"); convert(baseType: "long", fromType: "nuint", toType: "E", "uint.MaxValue", "4294967295", "conv.u8", "4294967295", "conv.ovf.i8.un"); convert(baseType: "long", fromType: "System.IntPtr", toType: "E", "int.MinValue", "-2147483648", "conv.i8", "-2147483648", "conv.i8"); convert(baseType: "long", fromType: "System.IntPtr", toType: "E", "int.MaxValue", "2147483647", "conv.i8", "2147483647", "conv.i8"); convert(baseType: "long", fromType: "System.UIntPtr", toType: "E", "uint.MaxValue", "4294967295", "conv.u8", "4294967295", "conv.ovf.i8.un"); convert(baseType: "ulong", fromType: "E", toType: "nint", "ulong.MaxValue", "-1", "conv.i", "System.OverflowException", "conv.ovf.i.un"); convert(baseType: "ulong", fromType: "E", toType: "nuint", "ulong.MaxValue", IntPtr.Size == 4 ? "4294967295" : "18446744073709551615", "conv.u", IntPtr.Size == 4 ? "System.OverflowException" : "18446744073709551615", "conv.ovf.u.un"); convert(baseType: "ulong", fromType: "nint", toType: "E", "int.MinValue", "18446744071562067968", "conv.i8", "System.OverflowException", "conv.ovf.u8"); convert(baseType: "ulong", fromType: "nint", toType: "E", "int.MaxValue", "2147483647", "conv.i8", "2147483647", "conv.ovf.u8"); convert(baseType: "ulong", fromType: "nuint", toType: "E", "uint.MaxValue", "4294967295", "conv.u8", "4294967295", "conv.u8"); convert(baseType: "ulong", fromType: "System.IntPtr", toType: "E", "int.MinValue", "18446744071562067968", "conv.i8", "System.OverflowException", "conv.ovf.u8"); convert(baseType: "ulong", fromType: "System.IntPtr", toType: "E", "int.MaxValue", "2147483647", "conv.i8", "2147483647", "conv.ovf.u8"); convert(baseType: "ulong", fromType: "System.UIntPtr", toType: "E", "uint.MaxValue", "4294967295", "conv.u8", "4294967295", "conv.u8"); void convert(string baseType, string fromType, string toType, string fromValue, string toValueUnchecked, string toConvUnchecked, string toValueChecked, string toConvChecked) { if (baseType != null) baseType = " : " + baseType; string source = $@"using System; enum E{baseType} {{ A, B }} class Program {{ static {toType} Convert({fromType} value) => ({toType})(value); static {toType} ConvertChecked({fromType} value) => checked(({toType})(value)); static object Execute(Func<object> f) {{ try {{ return f(); }} catch (Exception e) {{ return e.GetType().FullName; }} }} static void Main() {{ {fromType} value = ({fromType})({fromValue}); Console.WriteLine(Execute(() => Convert(value))); Console.WriteLine(Execute(() => ConvertChecked(value))); }} }}"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9, options: TestOptions.ReleaseExe, targetFramework: TargetFramework.Net70); var verifier = CompileAndVerify(comp, verify: Verification.FailsPEVerify, expectedOutput: IncludeExpectedOutput( $@"{toValueUnchecked} {toValueChecked}")); verifier.VerifyIL("Program.Convert", $@"{{ // Code size 3 (0x3) .maxstack 1 IL_0000: ldarg.0 IL_0001: {toConvUnchecked} IL_0002: ret }}"); verifier.VerifyIL("Program.ConvertChecked", $@"{{ // Code size 3 (0x3) .maxstack 1 IL_0000: ldarg.0 IL_0001: {toConvChecked} IL_0002: ret }}"); } } [Theory] [InlineData("nint", "System.IntPtr")] [InlineData("nuint", "System.UIntPtr")] public void MethodTypeInference(string nativeIntegerType, string underlyingType) { var source = $@"interface I<T> {{ T P {{ get; }} }} unsafe class Program {{ static T F0<T>(T x, T y) => x; static void F1({nativeIntegerType} x, {underlyingType} y) {{ var z = ({nativeIntegerType})y; F0(x, z).ToPointer(); F0(x, y).ToPointer(); F0(y, x).ToPointer(); F0<{nativeIntegerType}>(x, y). ToPointer(); F0<{underlyingType}>(x, y). ToPointer(); }} static void F2({nativeIntegerType}[] x, {underlyingType}[] y) {{ var z = ({nativeIntegerType}[])y; F0(x, z)[0].ToPointer(); F0(x, y)[0].ToPointer(); F0(y, x)[0].ToPointer(); F0<{nativeIntegerType}[]>(x, y)[0]. ToPointer(); F0<{underlyingType}[]>(x, y)[0]. ToPointer(); }} static void F3(I<{nativeIntegerType}> x, I<{underlyingType}> y) {{ var z = (I<{nativeIntegerType}>)y; F0(x, z).P.ToPointer(); F0(x, y).P.ToPointer(); F0(y, x).P.ToPointer(); F0<I<{nativeIntegerType}>>(x, y).P. ToPointer(); F0<I<{underlyingType}>>(x, y).P. ToPointer(); }} }}"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9, options: TestOptions.UnsafeReleaseDll, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); } [Fact] public void DuplicateConstraint() { var source = @"interface I<T> { } class C1<T, U> where U : I<nint>, I<nint> { } class C2<T, U> where U : I<nint>, I<System.IntPtr> { } class C3<T, U> where U : I<System.UIntPtr>, I<System.IntPtr>, I<nuint> { } "; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics( // (2,35): error CS0405: Duplicate constraint 'I<nint>' for type parameter 'U' // class C1<T, U> where U : I<nint>, I<nint> { } Diagnostic(ErrorCode.ERR_DuplicateBound, "I<nint>").WithArguments("I<nint>", "U").WithLocation(2, 35), // (3,35): error CS0405: Duplicate constraint 'I<nint>' for type parameter 'U' // class C2<T, U> where U : I<nint>, I<System.IntPtr> { } Diagnostic(ErrorCode.ERR_DuplicateBound, "I<System.IntPtr>").WithArguments("I<nint>", "U").WithLocation(3, 35), // (4,63): error CS0405: Duplicate constraint 'I<nuint>' for type parameter 'U' // class C3<T, U> where U : I<System.UIntPtr>, I<System.IntPtr>, I<nuint> { } Diagnostic(ErrorCode.ERR_DuplicateBound, "I<nuint>").WithArguments("I<nuint>", "U").WithLocation(4, 63)); } [Fact] public void DuplicateInterface_01() { var source = @"interface I<T> { } class C1 : I<nint>, I<nint> { } class C2 : I<nint>, I<System.IntPtr> { } class C3 : I<System.UIntPtr>, I<System.IntPtr>, I<nuint> { } "; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics( // (2,21): error CS0528: 'I<nint>' is already listed in interface list // class C1 : I<nint>, I<nint> { } Diagnostic(ErrorCode.ERR_DuplicateInterfaceInBaseList, "I<nint>").WithArguments("I<nint>").WithLocation(2, 21), // (3,21): error CS0528: 'I<nint>' is already listed in interface list // class C2 : I<nint>, I<System.IntPtr> { } Diagnostic(ErrorCode.ERR_DuplicateInterfaceInBaseList, "I<System.IntPtr>").WithArguments("I<nint>").WithLocation(3, 21), // (4,49): error CS0528: 'I<nuint>' is already listed in interface list // class C3 : I<System.UIntPtr>, I<System.IntPtr>, I<nuint> { } Diagnostic(ErrorCode.ERR_DuplicateInterfaceInBaseList, "I<nuint>").WithArguments("I<nuint>").WithLocation(4, 49)); } [Theory] [InlineData("nuint")] [InlineData("System.UIntPtr")] public void SignedToUnsignedConversions_Implicit(string type) { string source = $@"static class NativeInts {{ static {type} Implicit1(sbyte x) => x; // 1 static {type} Implicit2(short x) => x; // 2 static {type} Implicit3(int x) => x; // 3 static {type} Implicit4(long x) => x; // 4 static {type} Implicit5(nint x) => x; // 5 static {type} Checked1(sbyte x) => checked(x); // 6 static {type} Checked2(short x) => checked(x); // 7 static {type} Checked3(int x) => checked(x); // 8 static {type} Checked4(long x) => checked(x); // 9 static {type} Checked5(nint x) => checked(x); // 10 }}"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics( // (3,40): error CS0266: Cannot implicitly convert type 'sbyte' to 'nuint'. An explicit conversion exists (are you missing a cast?) // static nuint Implicit1(sbyte x) => x; // 1 Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("sbyte", "nuint"), // (4,40): error CS0266: Cannot implicitly convert type 'short' to 'nuint'. An explicit conversion exists (are you missing a cast?) // static nuint Implicit2(short x) => x; // 2 Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("short", "nuint"), // (5,38): error CS0266: Cannot implicitly convert type 'int' to 'nuint'. An explicit conversion exists (are you missing a cast?) // static nuint Implicit3(int x) => x; // 3 Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("int", "nuint"), // (6,39): error CS0266: Cannot implicitly convert type 'long' to 'nuint'. An explicit conversion exists (are you missing a cast?) // static nuint Implicit4(long x) => x; // 4 Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("long", "nuint"), // (7,39): error CS0266: Cannot implicitly convert type 'nint' to 'nuint'. An explicit conversion exists (are you missing a cast?) // static nuint Implicit5(nint x) => x; // 5 Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("nint", "nuint"), // (8,47): error CS0266: Cannot implicitly convert type 'sbyte' to 'nuint'. An explicit conversion exists (are you missing a cast?) // static nuint Checked1(sbyte x) => checked(x); // 6 Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("sbyte", "nuint"), // (9,47): error CS0266: Cannot implicitly convert type 'short' to 'nuint'. An explicit conversion exists (are you missing a cast?) // static nuint Checked2(short x) => checked(x); // 7 Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("short", "nuint"), // (10,45): error CS0266: Cannot implicitly convert type 'int' to 'nuint'. An explicit conversion exists (are you missing a cast?) // static nuint Checked3(int x) => checked(x); // 8 Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("int", "nuint"), // (11,46): error CS0266: Cannot implicitly convert type 'long' to 'nuint'. An explicit conversion exists (are you missing a cast?) // static nuint Checked4(long x) => checked(x); // 9 Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("long", "nuint"), // (12,46): error CS0266: Cannot implicitly convert type 'nint' to 'nuint'. An explicit conversion exists (are you missing a cast?) // static nuint Checked5(nint x) => checked(x); // 10 Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("nint", "nuint")); } [Theory] [InlineData("nuint")] [InlineData("System.UIntPtr")] public void SignedToUnsignedConversions_Explicit(string type) { string source = $@"static class NativeInts {{ static {type} Explicit1(sbyte x) => ({type})x; static {type} Explicit2(short x) => ({type})x; static {type} Explicit3(int x) => ({type})x; static {type} Explicit4(long x) => ({type})x; static {type} Explicit5(nint x) => ({type})x; static {type} Checked1(sbyte x) => checked(({type})x); static {type} Checked2(short x) => checked(({type})x); static {type} Checked3(int x) => checked(({type})x); static {type} Checked4(long x) => checked(({type})x); static {type} Checked5(nint x) => checked(({type})x); }}"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); var verifier = CompileAndVerify(comp, verify: Verification.FailsPEVerify); string expectedExplicitILNop = @"{ // Code size 2 (0x2) .maxstack 1 IL_0000: ldarg.0 IL_0001: ret }"; string expectedExplicitILA = @"{ // Code size 3 (0x3) .maxstack 1 IL_0000: ldarg.0 IL_0001: conv.i IL_0002: ret }"; string expectedExplicitILB = @"{ // Code size 3 (0x3) .maxstack 1 IL_0000: ldarg.0 IL_0001: conv.u IL_0002: ret }"; string expectedCheckedIL = @"{ // Code size 3 (0x3) .maxstack 1 IL_0000: ldarg.0 IL_0001: conv.ovf.u IL_0002: ret }"; verifier.VerifyIL("NativeInts.Explicit1", expectedExplicitILA); verifier.VerifyIL("NativeInts.Explicit2", expectedExplicitILA); verifier.VerifyIL("NativeInts.Explicit3", expectedExplicitILA); verifier.VerifyIL("NativeInts.Explicit4", expectedExplicitILB); verifier.VerifyIL("NativeInts.Explicit5", expectedExplicitILNop); verifier.VerifyIL("NativeInts.Checked1", expectedCheckedIL); verifier.VerifyIL("NativeInts.Checked2", expectedCheckedIL); verifier.VerifyIL("NativeInts.Checked3", expectedCheckedIL); verifier.VerifyIL("NativeInts.Checked4", expectedCheckedIL); verifier.VerifyIL("NativeInts.Checked5", expectedCheckedIL); } [Fact] public void StandardConversions() { // Note: A standard explicit conversion is derived from opposite standard implicit conversion // type to nint verify(sourceType: "object", destType: "nint", isExplicit: true); verify(sourceType: "string", destType: "nint", noConversion: true); verify(sourceType: "void*", destType: "nint", noConversion: true); verify(sourceType: "delegate*<void>", destType: "nint", noConversion: true); verify(sourceType: "E", destType: "nint", noConversion: true); verify(sourceType: "bool", destType: "nint", noConversion: true); verify(sourceType: "sbyte", destType: "nint"); verify(sourceType: "byte", destType: "nint"); verify(sourceType: "short", destType: "nint"); verify(sourceType: "ushort", destType: "nint"); verify(sourceType: "int", destType: "nint"); verify(sourceType: "uint", destType: "nint", noConversion: true); verify(sourceType: "long", destType: "nint", isExplicit: true); verify(sourceType: "ulong", destType: "nint", noConversion: true); verify(sourceType: "char", destType: "nint"); verify(sourceType: "float", destType: "nint", isExplicit: true); verify(sourceType: "double", destType: "nint", isExplicit: true); verify(sourceType: "decimal", destType: "nint", isExplicit: true); verify(sourceType: "nint", destType: "nint"); verify(sourceType: "nuint", destType: "nint", noConversion: true); verify(sourceType: "System.IntPtr", destType: "nint"); verify(sourceType: "System.UIntPtr", destType: "nint", noConversion: true); // nint to type verify(sourceType: "nint", destType: "string", noConversion: true); verify(sourceType: "nint", destType: "void*", noConversion: true); verify(sourceType: "nint", destType: "delegate*<void>", noConversion: true); verify(sourceType: "nint", destType: "E", noConversion: true); verify(sourceType: "nint", destType: "bool", noConversion: true); verify(sourceType: "nint", destType: "sbyte", isExplicit: true); verify(sourceType: "nint", destType: "byte", isExplicit: true); verify(sourceType: "nint", destType: "short", isExplicit: true); verify(sourceType: "nint", destType: "ushort", isExplicit: true); verify(sourceType: "nint", destType: "int", isExplicit: true); verify(sourceType: "nint", destType: "uint", noConversion: true); verify(sourceType: "nint", destType: "long"); verify(sourceType: "nint", destType: "ulong", noConversion: true); verify(sourceType: "nint", destType: "char", isExplicit: true); verify(sourceType: "nint", destType: "float"); verify(sourceType: "nint", destType: "double"); verify(sourceType: "nint", destType: "decimal"); verify(sourceType: "nint", destType: "nint"); verify(sourceType: "nint", destType: "nuint", noConversion: true); verify(sourceType: "nint", destType: "System.IntPtr"); verify(sourceType: "nint", destType: "System.UIntPtr", noConversion: true); // type to nuint verify(sourceType: "object", destType: "nuint", isExplicit: true); verify(sourceType: "string", destType: "nuint", noConversion: true); verify(sourceType: "void*", destType: "nuint", noConversion: true); verify(sourceType: "delegate*<void>", destType: "nuint", noConversion: true); verify(sourceType: "E", destType: "nuint", noConversion: true); verify(sourceType: "bool", destType: "nuint", noConversion: true); verify(sourceType: "sbyte", destType: "nuint", noConversion: true); verify(sourceType: "byte", destType: "nuint"); verify(sourceType: "short", destType: "nuint", noConversion: true); verify(sourceType: "ushort", destType: "nuint"); verify(sourceType: "int", destType: "nuint", noConversion: true); verify(sourceType: "uint", destType: "nuint"); verify(sourceType: "long", destType: "nuint", noConversion: true); verify(sourceType: "ulong", destType: "nuint", isExplicit: true); verify(sourceType: "char", destType: "nuint"); verify(sourceType: "float", destType: "nuint", isExplicit: true); verify(sourceType: "double", destType: "nuint", isExplicit: true); verify(sourceType: "decimal", destType: "nuint", isExplicit: true); verify(sourceType: "nint", destType: "nuint", noConversion: true); verify(sourceType: "nuint", destType: "nuint"); verify(sourceType: "System.IntPtr", destType: "nuint", noConversion: true); verify(sourceType: "System.UIntPtr", destType: "nuint"); // nuint to type verify(sourceType: "nuint", destType: "string", noConversion: true); verify(sourceType: "nuint", destType: "void*", noConversion: true); verify(sourceType: "nuint", destType: "delegate*<void>", noConversion: true); verify(sourceType: "nuint", destType: "E", noConversion: true); verify(sourceType: "nuint", destType: "bool", noConversion: true); verify(sourceType: "nuint", destType: "sbyte", noConversion: true); verify(sourceType: "nuint", destType: "byte", isExplicit: true); verify(sourceType: "nuint", destType: "short", noConversion: true); verify(sourceType: "nuint", destType: "ushort", isExplicit: true); verify(sourceType: "nuint", destType: "int", noConversion: true); verify(sourceType: "nuint", destType: "uint", isExplicit: true); verify(sourceType: "nuint", destType: "long", noConversion: true); verify(sourceType: "nuint", destType: "ulong"); verify(sourceType: "nuint", destType: "char", isExplicit: true); verify(sourceType: "nuint", destType: "float"); verify(sourceType: "nuint", destType: "double"); verify(sourceType: "nuint", destType: "decimal"); verify(sourceType: "nuint", destType: "nint", noConversion: true); verify(sourceType: "nuint", destType: "nuint"); verify(sourceType: "nuint", destType: "System.IntPtr", noConversion: true); verify(sourceType: "nuint", destType: "System.UIntPtr"); // type to IntPtr verify(sourceType: "object", destType: "System.IntPtr", isExplicit: true); verify(sourceType: "string", destType: "System.IntPtr", noConversion: true); verify(sourceType: "void*", destType: "System.IntPtr", noConversion: true); verify(sourceType: "delegate*<void>", destType: "System.IntPtr", noConversion: true); verify(sourceType: "E", destType: "System.IntPtr", noConversion: true); verify(sourceType: "bool", destType: "System.IntPtr", noConversion: true); verify(sourceType: "sbyte", destType: "System.IntPtr"); verify(sourceType: "byte", destType: "System.IntPtr"); verify(sourceType: "short", destType: "System.IntPtr"); verify(sourceType: "ushort", destType: "System.IntPtr"); verify(sourceType: "int", destType: "System.IntPtr"); verify(sourceType: "uint", destType: "System.IntPtr", noConversion: true); verify(sourceType: "long", destType: "System.IntPtr", isExplicit: true); verify(sourceType: "ulong", destType: "System.IntPtr", noConversion: true); verify(sourceType: "char", destType: "System.IntPtr"); verify(sourceType: "float", destType: "System.IntPtr", isExplicit: true); verify(sourceType: "double", destType: "System.IntPtr", isExplicit: true); verify(sourceType: "decimal", destType: "System.IntPtr", isExplicit: true); verify(sourceType: "nint", destType: "System.IntPtr"); verify(sourceType: "nuint", destType: "System.IntPtr", noConversion: true); verify(sourceType: "System.IntPtr", destType: "System.IntPtr"); verify(sourceType: "System.UIntPtr", destType: "System.IntPtr", noConversion: true); // IntPtr to type verify(sourceType: "System.IntPtr", destType: "string", noConversion: true); verify(sourceType: "System.IntPtr", destType: "void*", noConversion: true); verify(sourceType: "System.IntPtr", destType: "delegate*<void>", noConversion: true); verify(sourceType: "System.IntPtr", destType: "E", noConversion: true); verify(sourceType: "System.IntPtr", destType: "bool", noConversion: true); verify(sourceType: "System.IntPtr", destType: "sbyte", isExplicit: true); verify(sourceType: "System.IntPtr", destType: "byte", isExplicit: true); verify(sourceType: "System.IntPtr", destType: "short", isExplicit: true); verify(sourceType: "System.IntPtr", destType: "ushort", isExplicit: true); verify(sourceType: "System.IntPtr", destType: "int", isExplicit: true); verify(sourceType: "System.IntPtr", destType: "uint", noConversion: true); verify(sourceType: "System.IntPtr", destType: "long"); verify(sourceType: "System.IntPtr", destType: "ulong", noConversion: true); verify(sourceType: "System.IntPtr", destType: "char", isExplicit: true); verify(sourceType: "System.IntPtr", destType: "float"); verify(sourceType: "System.IntPtr", destType: "double"); verify(sourceType: "System.IntPtr", destType: "decimal"); verify(sourceType: "System.IntPtr", destType: "nint"); verify(sourceType: "System.IntPtr", destType: "nuint", noConversion: true); verify(sourceType: "System.IntPtr", destType: "System.IntPtr"); verify(sourceType: "System.IntPtr", destType: "System.UIntPtr", noConversion: true); // type to UIntPtr verify(sourceType: "object", destType: "System.UIntPtr", isExplicit: true); verify(sourceType: "string", destType: "System.UIntPtr", noConversion: true); verify(sourceType: "void*", destType: "System.UIntPtr", noConversion: true); verify(sourceType: "delegate*<void>", destType: "System.UIntPtr", noConversion: true); verify(sourceType: "E", destType: "System.UIntPtr", noConversion: true); verify(sourceType: "bool", destType: "System.UIntPtr", noConversion: true); verify(sourceType: "sbyte", destType: "System.UIntPtr", noConversion: true); verify(sourceType: "byte", destType: "System.UIntPtr"); verify(sourceType: "short", destType: "System.UIntPtr", noConversion: true); verify(sourceType: "ushort", destType: "System.UIntPtr"); verify(sourceType: "int", destType: "System.UIntPtr", noConversion: true); verify(sourceType: "uint", destType: "System.UIntPtr"); verify(sourceType: "long", destType: "System.UIntPtr", noConversion: true); verify(sourceType: "ulong", destType: "System.UIntPtr", isExplicit: true); verify(sourceType: "char", destType: "System.UIntPtr"); verify(sourceType: "float", destType: "System.UIntPtr", isExplicit: true); verify(sourceType: "double", destType: "System.UIntPtr", isExplicit: true); verify(sourceType: "decimal", destType: "System.UIntPtr", isExplicit: true); verify(sourceType: "nint", destType: "System.UIntPtr", noConversion: true); verify(sourceType: "nuint", destType: "System.UIntPtr"); verify(sourceType: "System.IntPtr", destType: "System.UIntPtr", noConversion: true); verify(sourceType: "System.UIntPtr", destType: "System.UIntPtr"); // UIntPtr to type verify(sourceType: "System.UIntPtr", destType: "string", noConversion: true); verify(sourceType: "System.UIntPtr", destType: "void*", noConversion: true); verify(sourceType: "System.UIntPtr", destType: "delegate*<void>", noConversion: true); verify(sourceType: "System.UIntPtr", destType: "E", noConversion: true); verify(sourceType: "System.UIntPtr", destType: "bool", noConversion: true); verify(sourceType: "System.UIntPtr", destType: "sbyte", noConversion: true); verify(sourceType: "System.UIntPtr", destType: "byte", isExplicit: true); verify(sourceType: "System.UIntPtr", destType: "short", noConversion: true); verify(sourceType: "System.UIntPtr", destType: "ushort", isExplicit: true); verify(sourceType: "System.UIntPtr", destType: "int", noConversion: true); verify(sourceType: "System.UIntPtr", destType: "uint", isExplicit: true); verify(sourceType: "System.UIntPtr", destType: "long", noConversion: true); verify(sourceType: "System.UIntPtr", destType: "ulong"); verify(sourceType: "System.UIntPtr", destType: "char", isExplicit: true); verify(sourceType: "System.UIntPtr", destType: "float"); verify(sourceType: "System.UIntPtr", destType: "double"); verify(sourceType: "System.UIntPtr", destType: "decimal"); verify(sourceType: "System.UIntPtr", destType: "nint", noConversion: true); verify(sourceType: "System.UIntPtr", destType: "nuint"); verify(sourceType: "System.UIntPtr", destType: "System.IntPtr", noConversion: true); verify(sourceType: "System.UIntPtr", destType: "System.UIntPtr"); void verify(string sourceType, string destType, bool noConversion = false, bool isExplicit = false) { var source = $$""" unsafe class FinalType { FinalType M({{sourceType}} x) => x; FinalType M2({{sourceType}} x) => (FinalType)x; public static implicit operator FinalType({{destType}} i) => throw null; } enum E { } """; var comp = CreateCompilation(source, options: TestOptions.UnsafeDebugDll, targetFramework: TargetFramework.Net70); if (noConversion) { comp.VerifyDiagnostics( // (3,30): error CS0029: Cannot implicitly convert type 'sourceType' to 'FinalType' // FinalType M(sourceType x) => x; Diagnostic(ErrorCode.ERR_NoImplicitConv, "x").WithArguments(AsNative(sourceType), "FinalType"), // (4,31): error CS0030: Cannot convert type 'sourceType' to 'FinalType' // FinalType M2(sourceType x) => (FinalType)x; Diagnostic(ErrorCode.ERR_NoExplicitConv, "(FinalType)x").WithArguments(AsNative(sourceType), "FinalType") ); } else if (isExplicit) { comp.VerifyDiagnostics( // (3,30): error CS0266: Cannot implicitly convert type 'sourceType' to 'FinalType'. An explicit conversion exists (are you missing a cast?) // FinalType M(sourceType x) => x; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments(AsNative(sourceType), "FinalType") ); } else { comp.VerifyDiagnostics(); } } } [Theory] [InlineData(true)] [InlineData(false)] public void VerifyUnifiedSymbols(bool useCSharp11) { var corlib_cs = RuntimeFeature_NumericIntPtr + @" namespace System { public struct IntPtr { } public struct UIntPtr { } public class Object { } public class String { } public class ValueType { } public struct Void { } } "; var source = @" interface I { void M(nint x1, System.IntPtr x2, nuint x3, System.UIntPtr x4); } "; var parseOptions = (useCSharp11 ? TestOptions.Regular11 : TestOptions.Regular10).WithNoRefSafetyRulesAttribute(); var comp = CreateEmptyCompilation(new[] { source, corlib_cs }, parseOptions: parseOptions); verify(comp); var corlib = CreateEmptyCompilation(corlib_cs, parseOptions: parseOptions); corlib.VerifyDiagnostics(); comp = CreateEmptyCompilation(source, references: new[] { corlib.ToMetadataReference() }, parseOptions: parseOptions); verify(comp); comp = CreateEmptyCompilation(source, references: new[] { corlib.EmitToImageReference() }, parseOptions: parseOptions); verify(comp); void verify(CSharpCompilation comp) { comp.VerifyDiagnostics(); var emitOptions = new EmitOptions(runtimeMetadataVersion: "v5.1", debugInformationFormat: DebugInformationFormat.PortablePdb); comp.VerifyEmitDiagnostics(emitOptions); var method = (MethodSymbol)comp.GlobalNamespace.GetMember("I.M"); var nintType = method.Parameters[0].Type; verifyIntPtr(nintType); verifyCommon(nintType); var intPtrType = method.Parameters[1].Type; verifyIntPtr(intPtrType); verifyCommon(nintType); Assert.Same(nintType, intPtrType); Assert.Same(nintType, comp.GetSpecialType(SpecialType.System_IntPtr)); var fromAPI = comp.CreateNativeIntegerTypeSymbol(signed: true); Assert.Same(nintType, fromAPI); Assert.False(fromAPI.IsNativeIntegerWrapperType); var nuintType = method.Parameters[2].Type; verifyUIntPtr(nuintType); verifyCommon(nintType); var uintPtrType = method.Parameters[3].Type; verifyUIntPtr(uintPtrType); verifyCommon(nintType); Assert.Same(nuintType, uintPtrType); Assert.Same(nuintType, comp.GetSpecialType(SpecialType.System_UIntPtr)); fromAPI = comp.CreateNativeIntegerTypeSymbol(signed: false); Assert.Same(nuintType, fromAPI); Assert.False(fromAPI.IsNativeIntegerWrapperType); VerifyNoNativeIntegerAttributeEmitted(comp); } static void verifyIntPtr(TypeSymbol type) { Assert.Equal(SpecialType.System_IntPtr, type.SpecialType); Assert.Equal("nint", type.ToDisplayString(TestFormat)); Assert.Equal("nint", type.ToDisplayString(TestFormat)); Assert.Equal("System.IntPtr", type.ToDisplayString(TestFormat.WithCompilerInternalOptions(SymbolDisplayCompilerInternalOptions.UseNativeIntegerUnderlyingType))); Assert.Equal("nint", type.ToDisplayString(TestFormat.WithMiscellaneousOptions(SymbolDisplayMiscellaneousOptions.UseSpecialTypes))); } static void verifyUIntPtr(TypeSymbol type) { Assert.Equal(SpecialType.System_UIntPtr, type.SpecialType); Assert.Equal("nuint", type.ToDisplayString(TestFormat)); Assert.Equal("nuint", type.ToDisplayString(TestFormat)); Assert.Equal("System.UIntPtr", type.ToDisplayString(TestFormat.WithCompilerInternalOptions(SymbolDisplayCompilerInternalOptions.UseNativeIntegerUnderlyingType))); Assert.Equal("nuint", type.ToDisplayString(TestFormat.WithMiscellaneousOptions(SymbolDisplayMiscellaneousOptions.UseSpecialTypes))); } static void verifyCommon(TypeSymbol type) { Assert.True(type.IsDefinition); Assert.False(type.IsNativeIntegerWrapperType); Assert.Null(((NamedTypeSymbol)type).NativeIntegerUnderlyingType); } } [Fact] public void NoAttributesEmitted() { var source = @" interface I<T> { } class C1 : I<nint> { } class C2 : I<System.IntPtr> { } class C3 : I<nuint> { } class C4 : I<System.UIntPtr> { } class Base<T> { } class D1 : Base<nint> { } class D2 : Base<System.IntPtr> { } class D3 : Base<nuint> { } class D4 : Base<System.UIntPtr> { } class Misc { Misc(nint x1, System.IntPtr x2, nuint x3, System.UIntPtr x4) { } nint M1() => throw null; System.IntPtr M2() => throw null; nuint M3() => throw null; System.UIntPtr M4() => throw null; void Lambdas() { var lambda1 = nint () => throw null; var lambda2 = System.IntPtr () => throw null; var lambda3 = nuint () => throw null; var lambda4 = System.UIntPtr () => throw null; var lambda5 = void (nint x1, System.IntPtr x2, nuint x3, System.UIntPtr x4) => throw null; } void LocalFunctions() { local1(); local2(); local3(); local4(); local5(0, 0, 0, 0); nint local1() => throw null; System.IntPtr local2() => throw null; nuint local3() => throw null; System.UIntPtr local4() => throw null; void local5(nint x1, System.IntPtr x2, nuint x3, System.UIntPtr x4) { } } } delegate nint Delegate1(nint x); delegate System.IntPtr Delegate2(System.IntPtr x); delegate nuint Delegate3(nuint x); delegate System.UIntPtr Delegate4(System.UIntPtr x); class Operators { public static implicit operator Operators(nint x) => throw null; public static implicit operator Operators(nuint x) => throw null; } class Operators2 { public static implicit operator Operators2(System.IntPtr x) => throw null; public static implicit operator Operators2(System.UIntPtr x) => throw null; } class Constraints<T1, T2, T3, T4> where T1 : I<nint> where T2 : I<System.IntPtr> where T3 : I<nuint> where T4 : I<System.UIntPtr> { } class Properties { nint Property1 { get; set; } System.IntPtr Property2 { get; set; } nuint Property3 { get; set; } System.UIntPtr Property4 { get; set; } } class Indexers { nint this[nint x] => throw null; nuint this[nuint x] => throw null; } class Indexers2 { System.IntPtr Property2 => throw null; System.UIntPtr Property4 => throw null; } "; var comp = CreateCompilation(new[] { source }, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); VerifyNoNativeIntegerAttributeEmitted(comp); } [Fact] public void UserDefinedConversionOnSystemIntPtr() { var corlib_cs = RuntimeFeature_NumericIntPtr + @" namespace System { public struct IntPtr { public static implicit operator IntPtr(String s) { return 0; } } public struct UIntPtr { public static implicit operator UIntPtr(String s) { return 0; } } public class Object { } public class String { } public class ValueType { } public struct Void { } public struct Int32 { } public class Exception { } } "; var source = @" class C { nint M1(string s) { return s; } nuint M2(string s) { return s; } } "; var comp = CreateEmptyCompilation(new[] { source, corlib_cs }); comp.VerifyDiagnostics(); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var returnStatements = tree.GetRoot().DescendantNodes().OfType<ReturnStatementSyntax>().ToArray(); Assert.Equal("nint nint.op_Implicit(System.String s)", model.GetConversion(returnStatements[0].Expression).Method.ToDisplayString(TestFormat)); Assert.Equal("nuint nuint.op_Implicit(System.String s)", model.GetConversion(returnStatements[1].Expression).Method.ToDisplayString(TestFormat)); } [Fact] public void GenericAttribute_AttributeDependentTypes() { var source = @" #nullable enable using System; [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] class Attr<T> : Attribute { } [Attr<nint>] [Attr<D<nint>>] [Attr<nuint>] [Attr<D<nuint>>] class C1 { } [Attr<IntPtr>] [Attr<D<IntPtr>>] [Attr<UIntPtr>] [Attr<D<UIntPtr>>] class C2 { } class D<T> { } "; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); } [Fact] public void UnmanagedConstraint() { var source = @" class C<T> where T : unmanaged { } class D : C<System.IntPtr> { } "; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); } [Theory] [InlineData(false)] [InlineData(true)] public void RecordStructIntPtr(bool useCompilationReference) { var sourceA = @"namespace System { public class Object { public virtual bool Equals(object other) => default; public virtual int GetHashCode() => default; public virtual string ToString() => default; } public class String { } public abstract class ValueType { } public struct Void { } public struct Boolean { } public struct Int32 { } public struct Char { } public class Exception { } public interface IEquatable<T> { bool Equals(T other); } public class Attribute { } public class AttributeUsageAttribute : Attribute { public AttributeUsageAttribute(AttributeTargets validOn) { } public bool AllowMultiple { get; set; } public bool Inherited { get; set; } } public class Enum { } public enum AttributeTargets { } public record struct IntPtr { public static readonly IntPtr Zero; public static int Size => 0; public static IntPtr MaxValue => default; public static IntPtr MinValue => default; public static IntPtr Add(IntPtr ptr, int offset) => default; public static IntPtr Subtract(IntPtr ptr, int offset) => default; public static IntPtr Parse(string s) => default; public static bool TryParse(string s, out IntPtr value) { value = default; return false; } } public record struct UIntPtr { public static readonly UIntPtr Zero; public static int Size => 0; public static UIntPtr MaxValue => default; public static UIntPtr MinValue => default; public static UIntPtr Add(UIntPtr ptr, int offset) => default; public static UIntPtr Subtract(UIntPtr ptr, int offset) => default; public static UIntPtr Parse(string s) => default; public static bool TryParse(string s, out UIntPtr value) { value = default; return false; } } } namespace System.Text { public class StringBuilder { public StringBuilder Append(string s) => null; public StringBuilder Append(char c) => null; public StringBuilder Append(object o) => null; } } " + RuntimeFeature_NumericIntPtr; var comp = CreateEmptyCompilation(sourceA); comp.VerifyDiagnostics(); var refA = AsReference(comp, useCompilationReference); var sourceB = @"class Program { static nint F1() => throw null; static nuint F2() => throw null; static System.IntPtr F3() => throw null; static System.UIntPtr F4() => throw null; }"; comp = CreateEmptyCompilation(sourceB, references: new[] { refA }, parseOptions: TestOptions.Regular9); comp.VerifyDiagnostics(); var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); var methods = tree.GetRoot().DescendantNodes().OfType<MethodDeclarationSyntax>().ToArray(); Assert.Equal(4, methods.Count()); foreach (var method in methods) { var returnType = model.GetDeclaredSymbol(method).ReturnType; // record structs are erased in metadata Assert.Equal(useCompilationReference || returnType.IsReferenceType, returnType.IsRecord); } } [Fact] public void ArrayAccess() { var source = @" var array = new[] { 1, 2, 3, 4 }; nint x1 = 0; System.IntPtr x2 = 1; nuint x3 = 2; System.UIntPtr x4 = 3; System.Console.Write($""{array[x1]}, {array[x2]}, {array[x3]}, {array[x4]}""); "; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); CompileAndVerify(comp, expectedOutput: IncludeExpectedOutput("1, 2, 3, 4"), verify: Verification.FailsPEVerify); } [Fact] public void NativeIntegerAttributeFromMetadata() { var source = @" public class C { public nint M() { throw null; } }"; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); var image = comp.EmitToImageReference(); var comp2 = CreateCompilation(source, references: new[] { image }, targetFramework: TargetFramework.Net70); CompileAndVerify(comp2, sourceSymbolValidator: verify, symbolValidator: verify, verify: Verification.FailsPEVerify); static void verify(ModuleSymbol module) { var m = (MethodSymbol)module.GlobalNamespace.GetMember("C.M"); Assert.Equal("nint C.M()", m.ToDisplayString(TestFormat)); Assert.False(m.ReturnType.IsNativeIntegerWrapperType); } } [Fact] public void PatternExplainer() { var source = @" nint x = 0; _ = x switch // 1 { <= int.MaxValue => 0 }; _ = x switch // 2 { >= int.MinValue => 0 }; nuint y = 0; _ = y switch // 3 { <= uint.MaxValue => 0 }; "; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics( // (3,7): warning CS8509: The switch expression does not handle all possible values of its input type (it is not exhaustive). For example, the pattern '> (nint)int.MaxValue' is not covered. // _ = x switch // 1 Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustive, "switch").WithArguments("> (nint)int.MaxValue").WithLocation(3, 7), // (8,7): warning CS8509: The switch expression does not handle all possible values of its input type (it is not exhaustive). For example, the pattern '< (nint)int.MinValue' is not covered. // _ = x switch // 2 Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustive, "switch").WithArguments("< (nint)int.MinValue").WithLocation(8, 7), // (14,7): warning CS8509: The switch expression does not handle all possible values of its input type (it is not exhaustive). For example, the pattern '> (nuint)uint.MaxValue' is not covered. // _ = y switch // 3 Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustive, "switch").WithArguments("> (nuint)uint.MaxValue").WithLocation(14, 7) ); } [Theory, CombinatorialData] public void BetterConversionTarget(bool nullable1, bool nullable2) { // Given two types T1 and T2, T1 is a better conversion target than T2 if one of the following holds: // 1. An implicit conversion from T1 to T2 exists and no implicit conversion from T2 to T1 exists // ... // 3. T1 is S1 or S1? where S1 is a signed integral type, and T2 is S2 or S2? where S2 is an unsigned integral type. string s1Nullable = nullable1 ? "?" : ""; string s2Nullable = nullable2 ? "?" : ""; string source = $$""" using static System.Console; C.M1(0); C.M2(0); C.M3(0); C.M4(0); C.M5(0); C.M6(0); C.M7(0); C.M8(0); C.M9(0); public class C { public static void M1(sbyte{{s1Nullable}} x) { Write("M1 "); } public static void M1(nuint{{s2Nullable}} x) { } public static void M2(short{{s1Nullable}} x) { Write("M2 "); } public static void M2(nuint{{s2Nullable}} x) { } public static void M3(int{{s1Nullable}} x) { Write("M3 "); } public static void M3(nuint{{s2Nullable}} x) { } public static void M4(long{{s1Nullable}} x) { Write("M4 "); } public static void M4(nuint{{s2Nullable}} x) { } public static void M5(nint{{s1Nullable}} x) { Write("M5(nint) "); } public static void M5(ushort{{s2Nullable}} x) { Write("M5(ushort) "); } public static void M6(nint{{s1Nullable}} x) { Write("M6 "); } public static void M6(uint{{s2Nullable}} x) { } public static void M7(nint{{s1Nullable}} x) { Write("M7 "); } public static void M7(ulong{{s2Nullable}} x) { } public static void M8(nint{{s1Nullable}} x) { Write("M8 "); } public static void M8(nuint{{s2Nullable}} x) { } public static void M9(nint{{s1Nullable}} x) { Write("M9(nint)"); } public static void M9(byte{{s2Nullable}} x) { Write("M9(byte)"); } } """; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); // Note: conversions ushort->nint, ushort?->nint?, ushort->nint? are implicit (so rule 1 kicks in), but ushort?->nint is explicit (so rule 3 kicks in) var expected = (nullable1, nullable2) is (false, true) ? "M1 M2 M3 M4 M5(nint) M6 M7 M8 M9(nint)" : "M1 M2 M3 M4 M5(ushort) M6 M7 M8 M9(byte)"; CompileAndVerify(comp, expectedOutput: IncludeExpectedOutput(expected), verify: Verification.FailsPEVerify); } [Theory, CombinatorialData] public void BetterConversionTarget_IntPtr(bool nullable1, bool nullable2) { // Given two types T1 and T2, T1 is a better conversion target than T2 if one of the following holds: // 1. An implicit conversion from T1 to T2 exists and no implicit conversion from T2 to T1 exists // ... // 3. T1 is S1 or S1? where S1 is a signed integral type, and T2 is S2 or S2? where S2 is an unsigned integral type. string s1Nullable = nullable1 ? "?" : ""; string s2Nullable = nullable2 ? "?" : ""; string source = $$""" using System; using static System.Console; C.M1(0); C.M2(0); C.M3(0); C.M4(0); C.M5(0); C.M6(0); C.M7(0); C.M8(0); C.M9(0); C.M10(0); public class C { public static void M1(sbyte{{s1Nullable}} x) { Write("M1 "); } public static void M1(UIntPtr{{s2Nullable}} x) { } public static void M2(short{{s1Nullable}} x) { Write("M2 "); } public static void M2(UIntPtr{{s2Nullable}} x) { } public static void M3(int{{s1Nullable}} x) { Write("M3 "); } public static void M3(UIntPtr{{s2Nullable}} x) { } public static void M4(long{{s1Nullable}} x) { Write("M4 "); } public static void M4(UIntPtr{{s2Nullable}} x) { } public static void M5(nint{{s1Nullable}} x) { Write("M5 "); } public static void M5(UIntPtr{{s2Nullable}} x) { } public static void M6(IntPtr{{s1Nullable}} x) { Write("M6(IntPtr) "); } public static void M6(ushort{{s2Nullable}} x) { Write("M6(ushort) "); } public static void M7(IntPtr{{s1Nullable}} x) { Write("M7 "); } public static void M7(uint{{s2Nullable}} x) { } public static void M8(IntPtr{{s1Nullable}} x) { Write("M8 "); } public static void M8(ulong{{s2Nullable}} x) { } public static void M9(IntPtr{{s1Nullable}} x) { Write("M9 "); } public static void M9(nuint{{s2Nullable}} x) { } public static void M10(IntPtr{{s1Nullable}} x) { Write("M10(IntPtr)"); } public static void M10(byte{{s2Nullable}} x) { Write("M10(byte)"); } } """; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); // Note: conversions ushort->nint, ushort?->nint?, ushort->nint? are implicit (so rule 1 kicks in), but ushort?->nint is explicit (so rule 3 kicks in) var expected = (nullable1, nullable2) is (false, true) ? "M1 M2 M3 M4 M5 M6(IntPtr) M7 M8 M9 M10(IntPtr)" : "M1 M2 M3 M4 M5 M6(ushort) M7 M8 M9 M10(byte)"; CompileAndVerify(comp, expectedOutput: IncludeExpectedOutput(expected), verify: Verification.FailsPEVerify); } [Fact] public void RetargetingFromNonNumericToNumericIntPtrCorlib() { string lib_cs = """ public class Base { public virtual nint M() => 0; } """; var libComp = CreateEmptyCompilation(lib_cs, references: new[] { MscorlibRef_v20 }, assemblyName: "lib"); libComp.VerifyDiagnostics(); string source = """ public class Derived : Base { public override nint M() => 0; } """; var comp = CreateCompilation(source, references: new[] { libComp.ToMetadataReference() }, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); var baseM = (RetargetingMethodSymbol)comp.GlobalNamespace.GetMember("Base.M"); var baseNint = (PENamedTypeSymbol)baseM.ReturnType; var derivedM = (MethodSymbol)comp.GlobalNamespace.GetMember("Derived.M"); var derivedNint = (PENamedTypeSymbol)derivedM.ReturnType; Assert.Equal("nint", derivedNint.ToDisplayString(TestFormat)); Assert.Same(baseNint, derivedNint); } [Fact] public void RetargetingFromNumericIntPtrToNonNumericCorlib() { string lib_cs = """ public class Base { public virtual nint M() => 0; } """; var libComp = CreateCompilation(lib_cs, assemblyName: "lib", targetFramework: TargetFramework.Net70); libComp.VerifyDiagnostics(); string source = """ public class Derived : Base { public override nint M() => 0; } """; var comp = CreateEmptyCompilation(source, references: new[] { libComp.ToMetadataReference(), MscorlibRef_v46 }); comp.VerifyDiagnostics( // (1,24): error CS0012: The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Runtime, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. // public class Derived : Base Diagnostic(ErrorCode.ERR_NoTypeDef, "Base").WithArguments("System.Object", "System.Runtime, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a").WithLocation(1, 24) ); var baseM = (RetargetingMethodSymbol)comp.GlobalNamespace.GetMember("Base.M"); var baseNint = (PENamedTypeSymbol)baseM.ReturnType; var derivedM = (MethodSymbol)comp.GlobalNamespace.GetMember("Derived.M"); var derivedNint = (NativeIntegerTypeSymbol)derivedM.ReturnType; Assert.Equal("System.IntPtr", baseNint.ToDisplayString(TestFormat)); Assert.Equal("nint", derivedNint.ToDisplayString(TestFormat)); Assert.Same(baseNint, derivedNint.UnderlyingNamedType); } [Fact] public void UnsignedRightShift() { string source = """ public class C { nint M1(nint x, int count) => x >>> count; nuint M2(nuint x, int count) => x >>> count; nint M3(nint x, int count) => checked(x >>> count); nuint M4(nuint x, int count) => checked(x >>> count); System.IntPtr M5(System.IntPtr x, int count) => x >>> count; System.UIntPtr M6(System.UIntPtr x, int count) => x >>> count; } """; var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); var verifier = CompileAndVerify(comp, verify: Verification.FailsPEVerify); verifier.VerifyIL("C.M1", shiftRight("nint"), ilFormat: ILFormat); verifier.VerifyIL("C.M2", shiftRight("nuint"), ilFormat: ILFormat); verifier.VerifyIL("C.M3", shiftRight("nint"), ilFormat: ILFormat); verifier.VerifyIL("C.M4", shiftRight("nuint"), ilFormat: ILFormat); verifier.VerifyIL("C.M5", shiftRight("nint"), ilFormat: ILFormat); verifier.VerifyIL("C.M6", shiftRight("nuint"), ilFormat: ILFormat); return; static string shiftRight(string type) { return $$""" { // Code size 15 (0xf) .maxstack 4 IL_0000: ldarg.1 IL_0001: ldarg.2 IL_0002: sizeof "{{type}}" IL_0008: ldc.i4.8 IL_0009: mul IL_000a: ldc.i4.1 IL_000b: sub IL_000c: and IL_000d: shr.un IL_000e: ret } """; } } [Fact] public void OverflowPointerConversion() { // Breaking change string source = """ using System; class C { public unsafe static void Main() { void* ptr = (void*)ulong.MaxValue; try { IntPtr i = checked((IntPtr)ptr); } catch (System.OverflowException) { Console.Write("OVERFLOW "); } IntPtr j = unchecked((IntPtr)ptr); if (j == (IntPtr)(-1)) { Console.Write("RAN"); } } } """; var comp = CreateCompilation(source, options: TestOptions.UnsafeReleaseExe, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); CompileAndVerify(comp, expectedOutput: IncludeExpectedOutput("OVERFLOW RAN"), verify: Verification.Skipped); comp = CreateCompilation(source, options: TestOptions.UnsafeReleaseExe); comp.VerifyDiagnostics(); CompileAndVerify(comp, expectedOutput: IncludeExpectedOutput("RAN"), verify: Verification.Skipped); } [Fact] public void VariousMembersToDecodeOnRuntimeFeatureType() { var corlib_cs = @" namespace System { public struct IntPtr { } public struct UIntPtr { } public struct Boolean { } public class Object { } public class String { } public class ValueType { } public struct Void { } public struct Int32 { } public class Exception { } public class Delegate { public static Delegate CreateDelegate(Type type, object firstArgument, Reflection.MethodInfo method) => null; public static Delegate Combine(Delegate a, Delegate b) => null; public static Delegate Remove(Delegate source, Delegate value) => null; } public class Type { public Reflection.FieldInfo GetField(string name) => null; public static Type GetType(string name) => null; public static Type GetTypeFromHandle(RuntimeTypeHandle handle) => null; } public struct RuntimeMethodHandle { } public struct RuntimeTypeHandle { } public class MulticastDelegate : Delegate { } public class Attribute { } public class AttributeUsageAttribute : Attribute { public AttributeUsageAttribute(AttributeTargets t) { } public bool AllowMultiple { get; set; } public bool Inherited { get; set; } } public class Enum { } public enum AttributeTargets { } public delegate void Action(); namespace Reflection { public class AssemblyVersionAttribute : Attribute { public AssemblyVersionAttribute(string version) { } } public class DefaultMemberAttribute : Attribute { public DefaultMemberAttribute(string name) { } } public abstract class MemberInfo { } public abstract class MethodBase : MemberInfo { public static MethodBase GetMethodFromHandle(RuntimeMethodHandle handle) => throw null; } public abstract class MethodInfo : MethodBase { public virtual Delegate CreateDelegate(Type delegateType, object target) => throw null; } public abstract class FieldInfo : MemberInfo { public abstract object GetValue(object obj); } } } namespace System.Runtime.CompilerServices { public static class RuntimeFeature { public const string NumericIntPtr = nameof(NumericIntPtr); public static bool IsDynamicCodeCompiled => false; public static event Action MyEvent; public static bool Method(bool x) => true; class Nested { public const string A = nameof(NumericIntPtr); public static bool B => false; public static event Action C; public static bool D(bool x) => true; } } } "; var source = @" public class C { public nint field; public nuint field2; } "; var corlib = CreateEmptyCompilation(corlib_cs); var comp = CreateEmptyCompilation(source, references: new[] { corlib.EmitToImageReference() }); comp.VerifyDiagnostics(); } [Theory] [InlineData("nint")] [InlineData("nuint")] [InlineData("System.IntPtr")] [InlineData("System.UIntPtr")] public void XmlDoc_Cref(string type) { var src = $$""" /// <summary>Summary <see cref="{{type}}"/>.</summary> class C { } """; var comp = CreateCompilation(src, parseOptions: TestOptions.RegularWithDocumentationComments, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); var tree = comp.SyntaxTrees.Single(); var docComments = tree.GetCompilationUnitRoot().DescendantTrivia().Select(trivia => trivia.GetStructure()).OfType<DocumentationCommentTriviaSyntax>(); var cref = docComments.First().DescendantNodes().OfType<XmlCrefAttributeSyntax>().First().Cref; Assert.Equal(type, cref.ToString()); var model = comp.GetSemanticModel(tree, ignoreAccessibility: false); var nintSymbol = (INamedTypeSymbol)model.GetSymbolInfo(cref).Symbol; Assert.True(nintSymbol.IsNativeIntegerType); } [Fact] public void XmlDoc_Cref_Alias() { var src = """ using @nint = System.String; /// <summary>Summary <see cref="nint"/>.</summary> class C { } """; var comp = CreateCompilation(src, parseOptions: TestOptions.RegularWithDocumentationComments, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); var tree = comp.SyntaxTrees.Single(); var docComments = tree.GetCompilationUnitRoot().DescendantTrivia().Select(trivia => trivia.GetStructure()).OfType<DocumentationCommentTriviaSyntax>(); var cref = docComments.First().DescendantNodes().OfType<XmlCrefAttributeSyntax>().First().Cref; Assert.Equal("nint", cref.ToString()); var model = comp.GetSemanticModel(tree, ignoreAccessibility: false); var symbol = (INamedTypeSymbol)model.GetSymbolInfo(cref).Symbol; Assert.False(symbol.IsNativeIntegerType); Assert.Equal("System.String", symbol.ToTestDisplayString()); } [Theory] [InlineData("nint")] [InlineData("nuint")] public void XmlDoc_Cref_Member(string fieldName) { var src = $$""" /// <summary>Summary <see cref="{{fieldName}}"/>.</summary> public class C { /// <summary></summary> public int {{fieldName}}; } """; var comp = CreateCompilation(src, parseOptions: TestOptions.RegularWithDocumentationComments, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); var tree = comp.SyntaxTrees.Single(); var docComments = tree.GetCompilationUnitRoot().DescendantTrivia().Select(trivia => trivia.GetStructure()).OfType<DocumentationCommentTriviaSyntax>(); var cref = docComments.First().DescendantNodes().OfType<XmlCrefAttributeSyntax>().First().Cref; Assert.Equal(fieldName, cref.ToString()); var model = comp.GetSemanticModel(tree, ignoreAccessibility: false); var symbol = (IFieldSymbol)model.GetSymbolInfo(cref).Symbol; Assert.Equal($"System.Int32 C.{fieldName}", symbol.ToTestDisplayString()); } [Fact] public void XmlDoc_Cref_Member_Escaped() { var src = """ /// <summary>Summary <see cref="@nint"/>.</summary> public class C { /// <summary></summary> public int nint; } """; var comp = CreateCompilation(src, parseOptions: TestOptions.RegularWithDocumentationComments, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); var tree = comp.SyntaxTrees.Single(); var docComments = tree.GetCompilationUnitRoot().DescendantTrivia().Select(trivia => trivia.GetStructure()).OfType<DocumentationCommentTriviaSyntax>(); var cref = docComments.First().DescendantNodes().OfType<XmlCrefAttributeSyntax>().First().Cref; Assert.Equal("@nint", cref.ToString()); var model = comp.GetSemanticModel(tree, ignoreAccessibility: false); var symbol = (IFieldSymbol)model.GetSymbolInfo(cref).Symbol; Assert.Equal("System.Int32 C.nint", symbol.ToTestDisplayString()); } [Theory] [InlineData("@nint")] [InlineData("@nuint")] public void XmlDoc_Cref_Escaped(string type) { var src = $$""" /// <summary>Summary <see cref="{{type}}"/>.</summary> public class C { } """; var comp = CreateCompilation(src, parseOptions: TestOptions.RegularWithDocumentationComments, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics( // (1,33): warning CS1574: XML comment has cref attribute 'type' that could not be resolved // /// <summary>Summary <see cref="type"/>.</summary> Diagnostic(ErrorCode.WRN_BadXMLRef, type).WithArguments(type).WithLocation(1, 33) ); } [Fact] public void XmlDoc_Cref_Member_NintZero() { var src = """ /// <summary>Summary <see cref="nint.Zero"/>.</summary> public class C { /// <summary></summary> public int nint; } """; var comp = CreateCompilation(src, parseOptions: TestOptions.RegularWithDocumentationComments, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); var tree = comp.SyntaxTrees.Single(); var docComments = tree.GetCompilationUnitRoot().DescendantTrivia().Select(trivia => trivia.GetStructure()).OfType<DocumentationCommentTriviaSyntax>(); var cref = docComments.First().DescendantNodes().OfType<XmlCrefAttributeSyntax>().First().Cref; Assert.Equal("nint.Zero", cref.ToString()); var model = comp.GetSemanticModel(tree, ignoreAccessibility: false); var symbol = (IFieldSymbol)model.GetSymbolInfo(cref).Symbol; Assert.Equal("nint nint.Zero", symbol.ToDisplayString(TestFormat)); } [Fact, WorkItem(43347, "https://github.com/dotnet/roslyn/issues/43347")] public void MaskShiftCount() { // positive nint shift right validate("nint", "NIntMaxValue", ">> 0", "0x7FFF_FFFF", "0x7FFF_FFFF_FFFF_FFFF", nint_shr(0)); validate("nint", "NIntMaxValue", ">> 1", "0x3FFF_FFFF", "0x3FFF_FFFF_FFFF_FFFF", nint_shr(1)); validate("nint", "NIntMaxValue", ">> 31", "0x0", "0xFFFF_FFFF", nint_shr(31)); validate("nint", "NIntMaxValue", ">> 32", "0x7FFF_FFFF", "0x7FFF_FFFF", nint_shr(32)); validate("nint", "NIntMaxValue", ">> 33", "0x3FFF_FFFF", "0x3FFF_FFFF", nint_shr(33)); validate("nint", "NIntMaxValue", ">> 63", "0x0", "0x0", nint_shr(63)); validate("nint", "NIntMaxValue", ">> 64", "0x7FFF_FFFF", "0x7FFF_FFFF_FFFF_FFFF", nint_shr(64)); validate("nint", "NIntMaxValue", ">> 65", "0x3FFF_FFFF", "0x3FFF_FFFF_FFFF_FFFF", nint_shr(65)); // negative nint shift right validate("nint", "NIntNegativeValue", ">> 1", "0xE000_0000", "0xE000_0000_0000_0000", nint_shr(1)); validate("nint", "NIntNegativeValue", ">> 31", "0xFFFF_FFFF", "0xFFFF_FFFF_8000_0000", nint_shr(31)); validate("nint", "NIntNegativeValue", ">> 32", "0xC000_0001", "0xFFFF_FFFF_C000_0000", nint_shr(32)); validate("nint", "NIntNegativeValue", ">> 33", "0xE000_0000", "0xFFFF_FFFF_E000_0000", nint_shr(33)); validate("nint", "NIntNegativeValue", ">> 63", "0xFFFF_FFFF", "0xFFFF_FFFF_FFFF_FFFF", nint_shr(63)); validate("nint", "NIntNegativeValue", ">> 64", "0xC000_0001", "0xC000_0000_0000_0001", nint_shr(64)); // positive nint shift left validate("nint", "NIntMaxValue", "<< 0", "0x7FFF_FFFF", "0x7FFF_FFFF_FFFF_FFFF", nint_shl(0)); validate("nint", "NIntMaxValue", "<< 1", "0xFFFF_FFFE", "0xFFFF_FFFF_FFFF_FFFE", nint_shl(1)); validate("nint", "NIntMaxValue", "<< 31", "0x8000_0000", "0xFFFF_FFFF_8000_0000", nint_shl(31)); validate("nint", "NIntMaxValue", "<< 32", "0x7FFF_FFFF", "0xFFFF_FFFF_0000_0000", nint_shl(32)); validate("nint", "NIntMaxValue", "<< 63", "0x8000_0000", "0x8000_0000_0000_0000", nint_shl(63)); validate("nint", "NIntMaxValue", "<< 64", "0x7FFF_FFFF", "0x7FFF_FFFF_FFFF_FFFF", nint_shl(64)); // negative nint shift left validate("nint", "NIntNegativeValue", "<< 63", "0x8000_0000", "0x8000_0000_0000_0000", nint_shl(63)); // nuint shift right validate("nuint", "NUintMaxValue", ">> 0", "0xFFFF_FFFF", "0xFFFF_FFFF_FFFF_FFFF", nuint_shr_un(0)); validate("nuint", "NUintMaxValue", ">> 1", "0x7FFF_FFFF", "0x7FFF_FFFF_FFFF_FFFF", nuint_shr_un(1)); validate("nuint", "NUintMaxValue", ">> 31", "0x0000_0001", "0x0000_0001_FFFF_FFFF", nuint_shr_un(31)); validate("nuint", "NUintMaxValue", ">> 32", "0xFFFF_FFFF", "0x0000_0000_FFFF_FFFF", nuint_shr_un(32)); validate("nuint", "NUintMaxValue", ">> 63", "0x0000_0001", "0x0000_0000_0000_0001", nuint_shr_un(63)); validate("nuint", "NUintMaxValue", ">> 64", "0xFFFF_FFFF", "0xFFFF_FFFF_FFFF_FFFF", nuint_shr_un(64)); // nuint shift left validate("nuint", "NUintMaxValue", "<< 0", "0xFFFF_FFFF", "0xFFFF_FFFF_FFFF_FFFF", nuint_shl(0)); validate("nuint", "NUintMaxValue", "<< 1", "0xFFFF_FFFE", "0xFFFF_FFFF_FFFF_FFFE", nuint_shl(1)); validate("nuint", "NUintMaxValue", "<< 31", "0x8000_0000", "0xFFFF_FFFF_8000_0000", nuint_shl(31)); validate("nuint", "NUintMaxValue", "<< 32", "0xFFFF_FFFF", "0xFFFF_FFFF_0000_0000", nuint_shl(32)); validate("nuint", "NUintMaxValue", "<< 63", "0x8000_0000", "0x8000_0000_0000_0000", nuint_shl(63)); validate("nuint", "NUintMaxValue", "<< 64", "0xFFFF_FFFF", "0xFFFF_FFFF_FFFF_FFFF", nuint_shl(64)); // positive nint unsigned shift right validate("nint", "NIntMaxValue", ">>> 0", "0x7FFF_FFFF", "0x7FFF_FFFF_FFFF_FFFF", nint_shr_un(0)); validate("nint", "NIntMaxValue", ">>> 1", "0x3FFF_FFFF", "0x3FFF_FFFF_FFFF_FFFF", nint_shr_un(1)); validate("nint", "NIntMaxValue", ">>> 31", "0x0", "0xFFFF_FFFF", nint_shr_un(31)); validate("nint", "NIntMaxValue", ">>> 32", "0x7FFF_FFFF", "0x7FFF_FFFF", nint_shr_un(32)); validate("nint", "NIntMaxValue", ">>> 63", "0x0", "0x0", nint_shr_un(63)); validate("nint", "NIntMaxValue", ">>> 64", "0x7FFF_FFFF", "0x7FFF_FFFF_FFFF_FFFF", nint_shr_un(64)); // negative nint unsigned shift right validate("nint", "NIntNegativeValue", ">>> 0", "0xC000_0001", "0xC000_0000_0000_0001", nint_shr_un(0)); validate("nint", "NIntNegativeValue", ">>> 1", "0x6000_0000", "0x6000_0000_0000_0000", nint_shr_un(1)); validate("nint", "NIntNegativeValue", ">>> 31", "0x1", "0x0000_0001_8000_0000", nint_shr_un(31)); validate("nint", "NIntNegativeValue", ">>> 32", "0xC000_0001", "0x0000_0000_C000_0000", nint_shr_un(32)); validate("nint", "NIntNegativeValue", ">>> 63", "0x1", "0x1", nint_shr_un(63)); validate("nint", "NIntNegativeValue", ">>> 64", "0xC000_0001", "0xC000_0000_0000_0001", nint_shr_un(64)); // nuint unsigned shift right validate("nuint", "NUintMaxValue", ">>> 0", "0xFFFF_FFFF", "0xFFFF_FFFF_FFFF_FFFF", nuint_shr_un(0)); validate("nuint", "NUintMaxValue", ">>> 1", "0x7FFF_FFFF", "0x7FFF_FFFF_FFFF_FFFF", nuint_shr_un(1)); validate("nuint", "NUintMaxValue", ">>> 31", "0x0000_0001", "0x0000_0001_FFFF_FFFF", nuint_shr_un(31)); validate("nuint", "NUintMaxValue", ">>> 32", "0xFFFF_FFFF", "0x0000_0000_FFFF_FFFF", nuint_shr_un(32)); validate("nuint", "NUintMaxValue", ">>> 63", "0x0000_0001", "0x0000_0000_0000_0001", nuint_shr_un(63)); validate("nuint", "NUintMaxValue", ">>> 64", "0xFFFF_FFFF", "0xFFFF_FFFF_FFFF_FFFF", nuint_shr_un(64)); // lifted value validate("nint?", "NIntMaxValue", ">> 0", "0x7FFF_FFFF", "0x7FFF_FFFF_FFFF_FFFF", liftedValue(0, "nint?", "shr")); validate("nint?", "NIntMaxValue", ">> 1", "0x3FFF_FFFF", "0x3FFF_FFFF_FFFF_FFFF", liftedValue(1, "nint?", "shr")); validate("nint?", "NIntMaxValue", ">> 65", "0x3FFF_FFFF", "0x3FFF_FFFF_FFFF_FFFF", liftedValue(65, "nint?", "shr")); validate("nint?", "NIntNegativeValue", ">> 65", "0xE000_0000", "0xE000_0000_0000_0000", liftedValue(65, "nint?", "shr")); validate("nint?", "NIntMaxValue", "<< 65", "0xFFFF_FFFE", "0xFFFF_FFFF_FFFF_FFFE", liftedValue(65, "nint?", "shl")); validate("nint?", "NIntNegativeValue", "<< 65", "0x8000_0002", "0x8000_0000_0000_0002", liftedValue(65, "nint?", "shl")); validate("nuint?", "NUintMaxValue", ">> 65", "0x7FFF_FFFF", "0x7FFF_FFFF_FFFF_FFFF", liftedValue(65, "nuint?", "shr.un")); validate("nuint?", "NUintMaxValue", "<< 65", "0xFFFF_FFFE", "0xFFFF_FFFF_FFFF_FFFE", liftedValue(65, "nuint?", "shl")); validate("nint?", "NIntMaxValue", ">>> 65", "0x3FFF_FFFF", "0x3FFF_FFFF_FFFF_FFFF", liftedValue(65, "nint?", "shr.un")); validate("nint?", "NIntNegativeValue", ">>> 65", "0x6000_0000", "0x6000_0000_0000_0000", liftedValue(65, "nint?", "shr.un")); validate("nuint?", "NUintMaxValue", ">>> 65", "0x7FFF_FFFF", "0x7FFF_FFFF_FFFF_FFFF", liftedValue(65, "nuint?", "shr.un")); // lifted count compileAndVerify(""" class C { nint? M(nint value, int? count) => value >> count; } """) .VerifyIL("C.M", @" { // Code size 49 (0x31) .maxstack 4 .locals init (nint V_0, int? V_1, nint? V_2) IL_0000: ldarg.1 IL_0001: stloc.0 IL_0002: ldarg.2 IL_0003: stloc.1 IL_0004: ldloca.s V_1 IL_0006: call ""readonly bool int?.HasValue.get"" IL_000b: brtrue.s IL_0017 IL_000d: ldloca.s V_2 IL_000f: initobj ""nint?"" IL_0015: ldloc.2 IL_0016: ret IL_0017: ldloc.0 IL_0018: ldloca.s V_1 IL_001a: call ""readonly int int?.GetValueOrDefault()"" IL_001f: sizeof ""nint"" IL_0025: ldc.i4.8 IL_0026: mul IL_0027: ldc.i4.1 IL_0028: sub IL_0029: and IL_002a: shr IL_002b: newobj ""nint?..ctor(nint)"" IL_0030: ret } ", ilFormat: ILFormat); // lifted value and lifted count compileAndVerify(""" class C { nint? M(nint? value, int? count) => value >> count; } """) .VerifyIL("C.M", @" { // Code size 63 (0x3f) .maxstack 4 .locals init (nint? V_0, int? V_1, nint? V_2) IL_0000: ldarg.1 IL_0001: stloc.0 IL_0002: ldarg.2 IL_0003: stloc.1 IL_0004: ldloca.s V_0 IL_0006: call ""readonly bool nint?.HasValue.get"" IL_000b: ldloca.s V_1 IL_000d: call ""readonly bool int?.HasValue.get"" IL_0012: and IL_0013: brtrue.s IL_001f IL_0015: ldloca.s V_2 IL_0017: initobj ""nint?"" IL_001d: ldloc.2 IL_001e: ret IL_001f: ldloca.s V_0 IL_0021: call ""readonly nint nint?.GetValueOrDefault()"" IL_0026: ldloca.s V_1 IL_0028: call ""readonly int int?.GetValueOrDefault()"" IL_002d: sizeof ""nint"" IL_0033: ldc.i4.8 IL_0034: mul IL_0035: ldc.i4.1 IL_0036: sub IL_0037: and IL_0038: shr IL_0039: newobj ""nint?..ctor(nint)"" IL_003e: ret } ", ilFormat: ILFormat); return; static string nint_shr(int count) => shift(count, "nint", "shr"); static string nint_shr_un(int count) => shift(count, "nint", "shr.un"); static string nint_shl(int count) => shift(count, "nint", "shl"); static string nuint_shr_un(int count) => shift(count, "nuint", "shr.un"); static string nuint_shl(int count) => shift(count, "nuint", "shl"); static string shift(int count, string type, string op) { if (count == 0) { return $@" {{ // Code size 2 (0x2) .maxstack 1 IL_0000: ldarg.0 IL_0001: ret }} "; } if (count == 1) { return $@" {{ // Code size 4 (0x4) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldc.i4.1 IL_0002: {op} IL_0003: ret }} "; } if (count <= 31) { return $@" {{ // Code size 5 (0x5) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldc.i4.s {count} IL_0003: {op} IL_0004: ret }} "; } return $@" {{ // Code size 16 (0x10) .maxstack 4 IL_0000: ldarg.0 IL_0001: ldc.i4.s {count} IL_0003: sizeof ""{type}"" IL_0009: ldc.i4.8 IL_000a: mul IL_000b: ldc.i4.1 IL_000c: sub IL_000d: and IL_000e: {op} IL_000f: ret }} "; } static string liftedValue(int count, string type, string op) { var strippedType = type.Trim('?'); if (count == 0) { return $@" {{ // Code size 34 (0x22) .maxstack 1 .locals init ({type} V_0, {type} V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool {type}.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""{type}"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly {strippedType} {type}.GetValueOrDefault()"" IL_001c: newobj ""{type}..ctor({strippedType})"" IL_0021: ret }}"; } if (count == 1) { return $@" {{ // Code size 36 (0x24) .maxstack 2 .locals init ({type} V_0, {type} V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool {type}.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""{type}"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly {strippedType} {type}.GetValueOrDefault()"" IL_001c: ldc.i4.1 IL_001d: {op} IL_001e: newobj ""{type}..ctor({strippedType})"" IL_0023: ret }} "; } Assert.True(count == 65); return $@" {{ // Code size 48 (0x30) .maxstack 4 .locals init ({type} V_0, {type} V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: call ""readonly bool {type}.HasValue.get"" IL_0009: brtrue.s IL_0015 IL_000b: ldloca.s V_1 IL_000d: initobj ""{type}"" IL_0013: ldloc.1 IL_0014: ret IL_0015: ldloca.s V_0 IL_0017: call ""readonly {strippedType} {type}.GetValueOrDefault()"" IL_001c: ldc.i4.s {count} IL_001e: sizeof ""{strippedType}"" IL_0024: ldc.i4.8 IL_0025: mul IL_0026: ldc.i4.1 IL_0027: sub IL_0028: and IL_0029: {op} IL_002a: newobj ""{type}..ctor({strippedType})"" IL_002f: ret }} "; } CompilationVerifier compileAndVerify(CSharpTestSource source) { var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70); return CompileAndVerify(comp, verify: Verification.FailsPEVerify); } void validate(string type, string value, string binaryOp, string result32Bits, string result64Bits, string expectedIL) { validateWithCheckedOrUnchecked(type, value, binaryOp, expectedIL, result32Bits, result64Bits, isChecked: true); validateWithCheckedOrUnchecked(type, value, binaryOp, expectedIL, result32Bits, result64Bits, isChecked: false); } void validateWithCheckedOrUnchecked(string type, string value, string binaryOp, string expectedIL, string result32Bits, string result64Bits, bool isChecked) { var checkedKeyword = isChecked ? "checked" : "unchecked"; var strippedType = type.Trim('?'); var source = $$""" class C { public static unsafe nint NIntMaxValue => (sizeof(nint) == 4) ? (nint)0x7FFF_FFFF : (nint)0x7FFF_FFFF_FFFF_FFFF; public static unsafe nint NIntNegativeValue => (sizeof(nint) == 4) ? (nint)0xC000_0001 : unchecked((nint)0xC000_0000_0000_0001); public static unsafe nuint NUintMaxValue => (sizeof(nint) == 4) ? (nuint)0xFFFF_FFFF : (nuint)0xFFFF_FFFF_FFFF_FFFF; public static {{type}} M({{type}} value) { return {{checkedKeyword}}(value {{binaryOp}}); } public static unsafe void Main() { if (sizeof(nint) == 4) { if (unchecked(({{type}}){{result32Bits}}) == ({{value}} {{binaryOp}})) { System.Console.Write("RAN"); } else { System.Console.Write($"Actual for '{{value}} {{binaryOp}}' (32-bit): {{{value}} {{binaryOp}}}"); } } else if (sizeof(nint) == 8) { if (unchecked(({{type}}){{result64Bits}}) == ({{value}} {{binaryOp}})) { System.Console.Write("RAN"); } else { System.Console.Write($"Actual for '{{value}} {{binaryOp}}' (64-bit): {{{value}} {{binaryOp}}}"); } } } } """; var comp = CreateCompilation(source, options: TestOptions.UnsafeReleaseExe, targetFramework: TargetFramework.Net70); var verifier = CompileAndVerify(comp, verify: Verification.FailsPEVerify, expectedOutput: IncludeExpectedOutput("RAN")); verifier.VerifyIL("C.M", expectedIL, ilFormat: ILFormat); } } [Fact] public void MaskShiftCount_NegativeCount() { var source = """ System.Console.WriteLine(C.ShiftRight(255)); static class C { public static nint ShiftRight(nint x) => x >> (-62); } """; var comp = CreateCompilation(source, options: TestOptions.UnsafeReleaseExe, targetFramework: TargetFramework.Net70); comp.VerifyDiagnostics(); var verifier = CompileAndVerify(comp, expectedOutput: IncludeExpectedOutput("63"), verify: Verification.FailsPEVerify); verifier.VerifyIL("C.ShiftRight", @" { // Code size 16 (0x10) .maxstack 4 IL_0000: ldarg.0 IL_0001: ldc.i4.s -62 IL_0003: sizeof ""nint"" IL_0009: ldc.i4.8 IL_000a: mul IL_000b: ldc.i4.1 IL_000c: sub IL_000d: and IL_000e: shr IL_000f: ret } ", ilFormat: ILFormat); } [WorkItem(63348, "https://github.com/dotnet/roslyn/issues/63348")] [Fact] public void ConditionalStackalloc() { var source = @"using System; class Program { static int F(int n) { Span<char> s = n < 10 ? stackalloc char[n] : new char[n]; return s[n - 1]; } static void Main() { Console.Write(F(1)); Console.Write(F(11)); } }"; var comp = CreateCompilation(new[] { TestSources.Span, source }, options: TestOptions.UnsafeReleaseExe); verify(comp); comp = CreateCompilation(new[] { source }, options: TestOptions.UnsafeReleaseExe, targetFramework: TargetFramework.Net70); verify(comp); void verify(CSharpCompilation comp) { comp.VerifyEmitDiagnostics(); var verifier = CompileAndVerify(comp, verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput("00")); verifier.VerifyIL("Program.F", """ { // Code size 48 (0x30) .maxstack 3 .locals init (System.Span<char> V_0, //s System.Span<char> V_1, int V_2) IL_0000: ldarg.0 IL_0001: ldc.i4.s 10 IL_0003: bge.s IL_0016 IL_0005: ldarg.0 IL_0006: stloc.2 IL_0007: ldloc.2 IL_0008: conv.u IL_0009: ldc.i4.2 IL_000a: mul.ovf.un IL_000b: localloc IL_000d: ldloc.2 IL_000e: newobj "System.Span<char>..ctor(void*, int)" IL_0013: stloc.1 IL_0014: br.s IL_0022 IL_0016: ldarg.0 IL_0017: newarr "char" IL_001c: call "System.Span<char> System.Span<char>.op_Implicit(char[])" IL_0021: stloc.1 IL_0022: ldloc.1 IL_0023: stloc.0 IL_0024: ldloca.s V_0 IL_0026: ldarg.0 IL_0027: ldc.i4.1 IL_0028: sub IL_0029: call "ref char System.Span<char>.this[int].get" IL_002e: ldind.u2 IL_002f: ret } """); } } [WorkItem(67041, "https://github.com/dotnet/roslyn/issues/67041")] [Theory] [CombinatorialData] public void PointerSubtraction(bool useNumericIntPtr) { var source = """ class Program { static unsafe long F(int* p1) { byte* p2 = (byte*)p1; p2++; return p2 - (byte*)p1; } } """; var comp = CreateCompilation( source, options: TestOptions.UnsafeReleaseDll, targetFramework: useNumericIntPtr ? TargetFramework.Net60 : TargetFramework.Net70); comp.VerifyEmitDiagnostics(); } private void VerifyNoNativeIntegerAttributeEmitted(CSharpCompilation comp) { // PEVerify is skipped because it reports "Type load failed" because of the above corlib, // not because of duplicate TypeRefs in this assembly. Replace the above corlib with the // actual corlib when that assembly contains UIntPtr.MaxValue or if we decide to support // nuint.MaxValue (since MaxValue could be used in this test instead). CompileAndVerify(comp, emitOptions: new EmitOptions(runtimeMetadataVersion: "v5.1", debugInformationFormat: DebugInformationFormat.PortablePdb), symbolValidator: module => Assert.Equal("", NativeIntegerAttributesVisitor.GetString((PEModuleSymbol)module)), verify: Verification.Skipped); } const string RuntimeFeature_NumericIntPtr = @" namespace System.Runtime.CompilerServices { public static class RuntimeFeature { public const string NumericIntPtr = nameof(NumericIntPtr); } } "; static string AsNative(string type) => type switch { "IntPtr" or "System.IntPtr" => "nint", "IntPtr?" or "System.IntPtr?" => "nint?", "UIntPtr" or "System.UIntPtr" => "nuint", "UIntPtr?" or "System.UIntPtr?" => "nuint?", var t => t }; } }