I've tried to reproduce a null-forgiving code applied to a value type, but it does not generate any warning: dotnetfiddle.net. In actual code, I'm getting a warning. I'm actually compiling with .NET Core 6.0.
I'm getting multiple compile-time warnings on a code base, some of them related to null-forgiving code. I'm trying to use either SomeNullableValue.Value
or SomeNullableValue!
, but the compiler complains I'm possibly passing null
argument to a function in both ways.
The case I'm dealing with now is an enum
that is initially null, but is assigned later in the same control flow; in this case, it is Ast.ContStmtTarget? t
, where Ast.ContStmtTarget
is an enum
:
NextToken();
Ast.ContStmtTarget? t = null;
if (CurrentToken.Type == Token.Keyword) {
switch (CurrentToken.StringValue) {
case "do": t = Ast.ContStmtTarget.Do; break;
case "for": t = Ast.ContStmtTarget.For; break;
case "loop": t = Ast.ContStmtTarget.Loop; break;
case "while": t = Ast.ContStmtTarget.While; break;
}
}
if (!t.HasValue) {
FatalError(0x80A0400, GetTokenSpan());
}
r = new Ast.ContStmt(t.Value);
The compiler is outputting warning in the last line, r = ...;
, with the column pointing to t.Value
. Also, the Ast.ContStmt
constructor takes a non-nullable value (the enum
).
...\Parser.cs(1410,38): warning CS8629: Nullable value type may be null.
I've put compilable project on GitHub (dotnet build
):
CodePudding user response:
compiler is warning you that you can reach that line with t == null. Does FatalError return? I assume it throws but the compiler doesnt know that
do
if (!t.HasValue) {
FatalError(0x80A0400, GetTokenSpan());
} else{
r = new Ast.ContStmt(t.Value);
}
CodePudding user response:
You can mark FatalError
with DoesNotReturnAttribute
to help compiler determine that code after if
is unreachable in case !t.HasValue
otherwise compiler can't verify that code will not actually be called:
[DoesNotReturn]
private void FatalError(int msgId, Span? span, Dictionary<string, object>? vars = null) {
throw new SyntaxException(Program.Collect(new Problem(msgId, false, vars, span.Value)));
}