提交 cb9ee8ce 编写于 作者: T Ty Overby 提交者: GitHub

Merge pull request #18657 from TyOverby/optimize-is-null

Optimize is null
......@@ -134,12 +134,33 @@ private bool IsIrrefutablePatternTest(BoundExpression test)
private BoundExpression CompareWithConstant(BoundExpression input, BoundExpression boundConstant)
{
return _factory.StaticCall(
_factory.SpecialType(SpecialType.System_Object),
"Equals",
_factory.Convert(_factory.SpecialType(SpecialType.System_Object), boundConstant),
_factory.Convert(_factory.SpecialType(SpecialType.System_Object), input)
);
var systemObject = _factory.SpecialType(SpecialType.System_Object);
if (boundConstant.ConstantValue == ConstantValue.Null)
{
if (input.Type.IsNonNullableValueType())
{
var systemBoolean = _factory.SpecialType(SpecialType.System_Boolean);
return RewriteNullableNullEquality(
syntax: _factory.Syntax,
kind: BinaryOperatorKind.NullableNullEqual,
loweredLeft: input,
loweredRight: boundConstant,
returnType: systemBoolean);
}
else
{
return _factory.ObjectEqual(_factory.Convert(systemObject, input), boundConstant);
}
}
else
{
return _factory.StaticCall(
systemObject,
"Equals",
_factory.Convert(systemObject, boundConstant),
_factory.Convert(systemObject, input)
);
}
}
private bool? MatchConstantValue(BoundExpression source, TypeSymbol targetType, bool requiredNullTest)
......
......@@ -13,6 +13,266 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen
{
public class CodeGenOperatorTests : CSharpTestBase
{
[Fact]
public void TestIsNullPattern()
{
var source = @"
using System;
class C
{
public static void Main()
{
var c = new C();
Console.Write(c is null);
}
}
";
// Release
var compilation = CompileAndVerify(source, expectedOutput: "False", options: TestOptions.ReleaseExe);
compilation.VerifyIL("C.Main", @"{
// Code size 14 (0xe)
.maxstack 2
IL_0000: newobj ""C..ctor()""
IL_0005: ldnull
IL_0006: ceq
IL_0008: call ""void System.Console.Write(bool)""
IL_000d: ret
}");
// Debug
compilation = CompileAndVerify(source, expectedOutput: "False", options: TestOptions.DebugExe);
compilation.VerifyIL("C.Main", @"{
// Code size 18 (0x12)
.maxstack 2
.locals init (C V_0) //c
IL_0000: nop
IL_0001: newobj ""C..ctor()""
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldnull
IL_0009: ceq
IL_000b: call ""void System.Console.Write(bool)""
IL_0010: nop
IL_0011: ret
}");
}
[Fact]
public void TestIsNullPatternGenericParam()
{
var source = @"
using System;
class C
{
public static void M<T>(T o)
{
Console.Write(o is null);
if (o is null)
{
Console.Write(""Branch taken"");
}
}
public static void Main()
{
M(new object());
}
}
";
CreateStandardCompilation(source).VerifyDiagnostics(
// (7,28): error CS0403: Cannot convert null to type parameter 'T' because it could be a non-nullable value type. Consider using 'default(T)' instead.
// Console.Write(o is null);
Diagnostic(ErrorCode.ERR_TypeVarCantBeNull, "null").WithArguments("T").WithLocation(7, 28),
// (8,18): error CS0403: Cannot convert null to type parameter 'T' because it could be a non-nullable value type. Consider using 'default(T)' instead.
// if (o is null)
Diagnostic(ErrorCode.ERR_TypeVarCantBeNull, "null").WithArguments("T").WithLocation(8, 18));
}
[Fact]
public void TestIsNullPatternGenericParamClass()
{
var source = @"
using System;
class C
{
public static void M<T>(T o) where T: class
{
Console.Write(o is null);
if (o is null) {
Console.Write("" Branch taken"");
}
}
public static void Main()
{
M(new object());
}
}
";
// Release
var compilation = CompileAndVerify(source, expectedOutput: "False", options: TestOptions.ReleaseExe);
compilation.VerifyIL("C.M<T>(T)", @"{
// Code size 33 (0x21)
.maxstack 2
IL_0000: ldarg.0
IL_0001: box ""T""
IL_0006: ldnull
IL_0007: ceq
IL_0009: call ""void System.Console.Write(bool)""
IL_000e: ldarg.0
IL_000f: box ""T""
IL_0014: brtrue.s IL_0020
IL_0016: ldstr "" Branch taken""
IL_001b: call ""void System.Console.Write(string)""
IL_0020: ret
}");
// Debug
compilation = CompileAndVerify(source, expectedOutput: "False", options: TestOptions.DebugExe);
compilation.VerifyIL("C.M<T>(T)", @"{
// Code size 43 (0x2b)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: box ""T""
IL_0007: ldnull
IL_0008: ceq
IL_000a: call ""void System.Console.Write(bool)""
IL_000f: nop
IL_0010: ldarg.0
IL_0011: box ""T""
IL_0016: ldnull
IL_0017: ceq
IL_0019: stloc.0
IL_001a: ldloc.0
IL_001b: brfalse.s IL_002a
IL_001d: nop
IL_001e: ldstr "" Branch taken""
IL_0023: call ""void System.Console.Write(string)""
IL_0028: nop
IL_0029: nop
IL_002a: ret
}");
}
[Fact]
public void TestIsNullPatternObjectLiteral()
{
var source = @"
using System;
class C
{
public static void Main()
{
Console.Write(((object)null) is null);
if (((object) null) is null) {
Console.Write("" Branch taken"");
}
}
}
";
// Release
var compilation = CompileAndVerify(source, expectedOutput: "True Branch taken", options: TestOptions.ReleaseExe);
compilation.VerifyIL("C.Main", @"{
// Code size 20 (0x14)
.maxstack 2
IL_0000: ldnull
IL_0001: ldnull
IL_0002: ceq
IL_0004: call ""void System.Console.Write(bool)""
IL_0009: ldstr "" Branch taken""
IL_000e: call ""void System.Console.Write(string)""
IL_0013: ret
}");
// Debug
compilation = CompileAndVerify(source, expectedOutput: "True Branch taken", options: TestOptions.DebugExe);
compilation.VerifyIL("C.Main", @"{
// Code size 33 (0x21)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldnull
IL_0002: ldnull
IL_0003: ceq
IL_0005: call ""void System.Console.Write(bool)""
IL_000a: nop
IL_000b: ldnull
IL_000c: ldnull
IL_000d: ceq
IL_000f: stloc.0
IL_0010: ldloc.0
IL_0011: brfalse.s IL_0020
IL_0013: nop
IL_0014: ldstr "" Branch taken""
IL_0019: call ""void System.Console.Write(string)""
IL_001e: nop
IL_001f: nop
IL_0020: ret
}");
}
[Fact]
public void TestIsNullPatternStringConstant()
{
var source = @"
using System;
class C
{
const String nullString = null;
public static void Main()
{
Console.Write(((string)null) is nullString);
if (((string) null) is nullString) {
Console.Write("" Branch taken"");
}
}
}
";
// Release
var compilation = CompileAndVerify(source, expectedOutput: "True Branch taken", options: TestOptions.ReleaseExe);
compilation.VerifyIL("C.Main", @"{
// Code size 20 (0x14)
.maxstack 2
IL_0000: ldnull
IL_0001: ldnull
IL_0002: ceq
IL_0004: call ""void System.Console.Write(bool)""
IL_0009: ldstr "" Branch taken""
IL_000e: call ""void System.Console.Write(string)""
IL_0013: ret
}");
// Debug
compilation = CompileAndVerify(source, expectedOutput: "True Branch taken", options: TestOptions.DebugExe);
compilation.VerifyIL("C.Main", @"{
// Code size 33 (0x21)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldnull
IL_0002: ldnull
IL_0003: ceq
IL_0005: call ""void System.Console.Write(bool)""
IL_000a: nop
IL_000b: ldnull
IL_000c: ldnull
IL_000d: ceq
IL_000f: stloc.0
IL_0010: ldloc.0
IL_0011: brfalse.s IL_0020
IL_0013: nop
IL_0014: ldstr "" Branch taken""
IL_0019: call ""void System.Console.Write(string)""
IL_001e: nop
IL_001f: nop
IL_0020: ret
}");
}
[Fact]
public void TestDelegateAndStringOperators()
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册