提交 bcd928be 编写于 作者: N Neal Gafter 提交者: GitHub

Report warning (always false) when testing null using pattern-is (#22458)

Fixes #20103
上级 b3453f12
......@@ -46,22 +46,29 @@ static Func<int> M(__arglist)
- https://github.com/dotnet/roslyn/issues/21485 In Roslyn 2.0, the `unsafe` modifier could be used on a local function without using the `/unsafe` flag on the compilation. In Roslyn 2.6 (Visual Studio 2017 verion 15.5) the compiler requires the `/unsafe` compilation flag, and produces a diagnostic if the flag is not used.
- https://github.com/dotnet/roslyn/issues/20210 In C# 7.2, there are some uses of the new pattern switch construct, in which the switch expression is a constant, for which the compiler will produce warnings or errors not previously produced.
> ``` c#
> switch (default(object))
> {
> case bool _:
> case true: // new error: case subsumed by previous cases
> case false: // new error: case subsumed by previous cases
> break;
> }
>
> switch (1)
> {
> case 1 when true:
> break;
> default:
> break; // new warning: unreachable code
> }
> ```
- https://github.com/dotnet/roslyn/issues/22578 In C# 7.1, the compiler would compute the wrong default value for an optional parameter of nullable type declared with the default literal. For instance, `void M(int? x = default)` would use `0` for the default parameter value, instead of `null`. In C# 7.2 (Visual Studio 2017 version 15.5), the proper default parameter value (`null`) is computed in such cases.
\ No newline at end of file
``` c#
switch (default(object))
{
case bool _:
case true: // new error: case subsumed by previous cases
case false: // new error: case subsumed by previous cases
break;
}
switch (1)
{
case 1 when true:
break;
default:
break; // new warning: unreachable code
}
```
- https://github.com/dotnet/roslyn/issues/20103 In C# 7.2, when testing a constant null expression against a declaration pattern in which the type is not inferred, the compiler will now warn that the expression is never of the provided type.
``` c#
const object o = null;
if (o is object res) { // warning CS0184: The given expression is never of the provided ('object') type
```
- https://github.com/dotnet/roslyn/issues/22578 In C# 7.1, the compiler would compute the wrong default value for an optional parameter of nullable type declared with the default literal. For instance, `void M(int? x = default)` would use `0` for the default parameter value, instead of `null`. In C# 7.2 (Visual Studio 2017 version 15.5), the proper default parameter value (`null`) is computed in such cases.
......@@ -28,6 +28,11 @@ private BoundExpression BindIsPatternExpression(IsPatternExpressionSyntax node,
}
var pattern = BindPattern(node.Pattern, expressionType, hasErrors, diagnostics);
if (!hasErrors && pattern is BoundDeclarationPattern p && !p.IsVar && expression.ConstantValue == ConstantValue.Null)
{
diagnostics.Add(ErrorCode.WRN_IsAlwaysFalse, node.Location, p.DeclaredType.Type);
}
return new BoundIsPatternExpression(
node, expression, pattern, GetSpecialType(SpecialType.System_Boolean, diagnostics, node), hasErrors);
}
......
......@@ -5945,8 +5945,10 @@ public void RefutablePatterns()
{
public static void Main(string[] args)
{
if (null as string is string) { }
if (null as string is string s1) { }
const string s = null;
if (s is string) { }
if (s is string s2) { }
if (""goo"" is string s3) { }
}
......@@ -5960,18 +5962,24 @@ void M1(int? i)
";
var compilation = CreateStandardCompilation(source);
compilation.VerifyDiagnostics(
// (12,13): warning CS0184: The given expression is never of the provided ('long') type
// (8,13): warning CS0184: The given expression is never of the provided ('string') type
// if (s is string) { }
Diagnostic(ErrorCode.WRN_IsAlwaysFalse, "s is string").WithArguments("string").WithLocation(8, 13),
// (9,13): warning CS0184: The given expression is never of the provided ('string') type
// if (s is string s2) { }
Diagnostic(ErrorCode.WRN_IsAlwaysFalse, "s is string s2").WithArguments("string").WithLocation(9, 13),
// (14,13): warning CS0184: The given expression is never of the provided ('long') type
// if (i is long) { }
Diagnostic(ErrorCode.WRN_IsAlwaysFalse, "i is long").WithArguments("long").WithLocation(12, 13),
// (13,18): error CS8121: An expression of type 'int?' cannot be handled by a pattern of type 'long'.
Diagnostic(ErrorCode.WRN_IsAlwaysFalse, "i is long").WithArguments("long").WithLocation(14, 13),
// (15,18): error CS8121: An expression of type 'int?' cannot be handled by a pattern of type 'long'.
// if (i is long l) { }
Diagnostic(ErrorCode.ERR_PatternWrongType, "long").WithArguments("int?", "long").WithLocation(13, 18),
// (14,17): error CS0103: The name 'b' does not exist in the current context
Diagnostic(ErrorCode.ERR_PatternWrongType, "long").WithArguments("int?", "long").WithLocation(15, 18),
// (16,17): error CS0103: The name 'b' does not exist in the current context
// switch (b) { case long m: break; }
Diagnostic(ErrorCode.ERR_NameNotInContext, "b").WithArguments("b").WithLocation(14, 17),
// (14,35): warning CS0162: Unreachable code detected
Diagnostic(ErrorCode.ERR_NameNotInContext, "b").WithArguments("b").WithLocation(16, 17),
// (16,35): warning CS0162: Unreachable code detected
// switch (b) { case long m: break; }
Diagnostic(ErrorCode.WRN_UnreachableCode, "break").WithLocation(14, 35)
Diagnostic(ErrorCode.WRN_UnreachableCode, "break").WithLocation(16, 35)
);
}
......@@ -6345,5 +6353,33 @@ static void Main()
Diagnostic(ErrorCode.ERR_SwitchExpressionValueExpected, @"Console.WriteLine(""Hello"")").WithArguments("void").WithLocation(6, 17)
);
}
[Fact, WorkItem(20103, "https://github.com/dotnet/roslyn/issues/20103")]
public void TestNullInInPattern()
{
var source =
@"using System;
class Program
{
static void Main()
{
const string s = null;
if (s is string) {} else { Console.Write(""Hello ""); }
if (s is string t) {} else { Console.WriteLine(""World""); }
}
}
";
var expectedOutput = @"Hello World";
var compilation = CreateStandardCompilation(source, options: TestOptions.ReleaseExe);
compilation.VerifyDiagnostics(
// (7,13): warning CS0184: The given expression is never of the provided ('string') type
// if (s is string) {} else { Console.Write("Hello "); }
Diagnostic(ErrorCode.WRN_IsAlwaysFalse, "s is string").WithArguments("string").WithLocation(7, 13),
// (8,13): warning CS0184: The given expression is never of the provided ('string') type
// if (s is string t) {} else { Console.WriteLine("World"); }
Diagnostic(ErrorCode.WRN_IsAlwaysFalse, "s is string t").WithArguments("string").WithLocation(8, 13)
);
CompileAndVerify(compilation, expectedOutput: expectedOutput);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册