提交 eec7d64b 编写于 作者: J Julien Couvreur 提交者: GitHub

Disallow `default ?? x` (#21757)

上级 b9c46eae
......@@ -25,3 +25,6 @@ Consider the case where the type of `a` is `System.Func<bool>` and you write `va
- https://github.com/dotnet/roslyn/issues/20208 In C# 7.0 and before C# 7.2, the compiler considered a local declared with a `var` type and a tuple literal value to be used. So it would not report a warning if that local was not used. The compiler now produces a diagnostic. For example, `var unused = (1, 2);`.
- https://github.com/dotnet/roslyn/issues/20873 In Roslyn 2.3, the `includePrivateMembers` parameter of the `EmitOptions` constructor was changed to use `true` as its default value. This is a binary compatibility break. So clients using this API may have to re-compile, to pick up the new default value. An update will include a mitigation (ignoring the old default value when trying to emit a full assembly).
- https://github.com/dotnet/roslyn/issues/21582 In C# 7.1, when the default literal was introduced, it was accepted on the left-hand-side of a null-coalescing operator. For instance, in `default ?? 1`. In C# 7.2, this compiler bug was fixed to match the specification, and an error is produced instead ("Operator '??' cannot be applied to operand 'default'").
......@@ -3274,15 +3274,7 @@ internal static ConstantValue GetAsOperatorConstantResult(TypeSymbol operandType
private BoundExpression GenerateNullCoalescingBadBinaryOpsError(BinaryExpressionSyntax node, BoundExpression leftOperand, BoundExpression rightOperand, Conversion leftConversion, DiagnosticBag diagnostics)
{
if (leftOperand.IsLiteralDefault() || rightOperand.IsLiteralDefault())
{
Error(diagnostics, ErrorCode.ERR_BadOpOnNullOrDefault, node, node.OperatorToken.Text, "default");
}
else
{
Error(diagnostics, ErrorCode.ERR_BadBinaryOps, node, SyntaxFacts.GetText(node.OperatorToken.Kind()), leftOperand.Display, rightOperand.Display);
}
Error(diagnostics, ErrorCode.ERR_BadBinaryOps, node, SyntaxFacts.GetText(node.OperatorToken.Kind()), leftOperand.Display, rightOperand.Display);
return new BoundNullCoalescingOperator(node, leftOperand, rightOperand,
leftConversion, CreateErrorType(), hasErrors: true);
......@@ -3300,6 +3292,14 @@ private BoundExpression BindNullCoalescingOperator(BinaryExpressionSyntax node,
Conversion.NoConversion, CreateErrorType(), hasErrors: true);
}
if (leftOperand.IsLiteralDefault())
{
Error(diagnostics, ErrorCode.ERR_BadOpOnNullOrDefault, node, node.OperatorToken.Text, "default");
return new BoundNullCoalescingOperator(node, leftOperand, rightOperand,
Conversion.NoConversion, CreateErrorType(), hasErrors: true);
}
// SPEC ERROR: The specification states:
// SPEC ERROR:
// SPEC ERROR: "A null coalescing expression of the form a??b requires 'a' to be of
......
......@@ -921,6 +921,7 @@ static void Main()
var q = default && 1;
var r = default || 1;
var s = default ?? 1;
var t = default ?? default(int?);
}
}
";
......@@ -974,6 +975,12 @@ static void Main()
// (23,17): error CS8310: Operator '||' cannot be applied to operand 'default'
// var r = default || 1;
Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default || 1").WithArguments("||", "default").WithLocation(23, 17),
// (24,17): error CS8310: Operator '??' cannot be applied to operand 'default'
// var s = default ?? 1;
Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default ?? 1").WithArguments("??", "default").WithLocation(24, 17),
// (25,17): error CS8310: Operator '??' cannot be applied to operand 'default'
// var t = default ?? default(int?);
Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "default ?? default(int?)").WithArguments("??", "default").WithLocation(25, 17),
// (20,13): warning CS0219: The variable 'o' is assigned but its value is never used
// var o = default == 1; // ok
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "o").WithArguments("o").WithLocation(20, 13),
......@@ -1009,7 +1016,8 @@ static void Main()
var p = 1 != default; // ok
var q = 1 && default;
var r = 1 || default;
var s = 1 ?? default;
var s = new object() ?? default; // ok
var t = 1 ?? default;
}
}
";
......@@ -1063,9 +1071,9 @@ static void Main()
// (23,17): error CS8310: Operator '||' cannot be applied to operand 'default'
// var r = 1 || default;
Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "1 || default").WithArguments("||", "default").WithLocation(23, 17),
// (24,17): error CS8310: Operator '??' cannot be applied to operand 'default'
// var s = 1 ?? default;
Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "1 ?? default").WithArguments("??", "default").WithLocation(24, 17),
// (25,17): error CS0019: Operator '??' cannot be applied to operands of type 'int' and 'default'
// var t = 1 ?? default;
Diagnostic(ErrorCode.ERR_BadBinaryOps, "1 ?? default").WithArguments("??", "int", "default").WithLocation(25, 17),
// (20,13): warning CS0219: The variable 'o' is assigned but its value is never used
// var o = 1 == default; // ok
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "o").WithArguments("o").WithLocation(20, 13),
......@@ -1075,6 +1083,26 @@ static void Main()
);
}
[Fact]
public void TestBinaryOperators4()
{
string source = @"
class C
{
static void Main()
{
var a = default(string) ?? """";
var b = default(int?) ?? default;
var c = null ?? default(int?);
System.Console.Write($""{a == """"} {b == 0} {c == null}"");
}
}
";
var comp = CreateStandardCompilation(source, parseOptions: TestOptions.Regular7_1, options: TestOptions.DebugExe);
comp.VerifyDiagnostics();
CompileAndVerify(comp, expectedOutput: "True True True");
}
[Fact]
public void WithUserDefinedPlusOperator()
{
......@@ -2211,9 +2239,9 @@ class Program
var comp = CreateCompilationWithMscorlibAndSystemCore(text, parseOptions: TestOptions.Regular7_1);
comp.VerifyDiagnostics(
// (6,47): error CS0845: An expression tree lambda may not contain a coalescing operator with a null or default literal left-hand side
// (6,47): error CS8310: Operator '??' cannot be applied to operand 'default'
// Expression<Func<object>> testExpr = () => default ?? "hello";
Diagnostic(ErrorCode.ERR_ExpressionTreeContainsBadCoalesce, "default").WithLocation(6, 47)
Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, @"default ?? ""hello""").WithArguments("??", "default").WithLocation(6, 47)
);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册