dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.32k stars 4.74k forks source link

Code annotation for Exceptions #79647

Closed linkdotnet closed 1 year ago

linkdotnet commented 1 year ago

Problem

In the current setup, there is no way of telling that a method will throw an exception so that the code after will not be executed. A small example:

bool Throw()
{
    try
    {
        ActionWhichMightThrow();
        return true;
    }
    catch (Exception)
    {
        AlwaysThrow();

        // Never reached, but we have to add this
        throw;
    }
}

[DoesNotReturn]
void AlwaysThrow() => throw new Exception();

Even though AlwaysThrow will never return and will throw an exception the method would not be compilable without the additional (and useless) throw at the end (or a return statement).

Real-world example

I encountered this problem most often in combination with ExceptionDispatchInfo:

try
{
    return waiter.WaitTask.GetAwaiter().GetResult();
}
catch (AggregateException e) when (e.InnerExceptions.Count == 1)
{
    ExceptionDispatchInfo.Capture(e.InnerExceptions[0]).Throw();

    // Unreachable code
    throw;
}

New behavior

We already have DoesNotReturn and DoesNotReturnIf which could be a good beginning. If a method is flagged by this annotation the compiler should understand that the code afterward will never be reached. In its current state DoesNotReturnIf only understands a boolean input, maybe a new DoesNotReturnIfNull would also be helpful.

PS: I did neither add this as a proposal nor as a bug as I wasn't sure what category fits best.

dotnet-issue-labeler[bot] commented 1 year ago

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

KalleOlaviNiemitalo commented 1 year ago

Making DoesNotReturnAttribute affect definite assignment and reachability was rejected in https://github.com/dotnet/csharplang/issues/2555#issuecomment-495694037 and https://github.com/dotnet/csharplang/issues/3826#issuecomment-681191954. Alternative C# language changes have been discussed in https://github.com/dotnet/csharplang/issues/538 and https://github.com/dotnet/csharplang/issues/739.

linkdotnet commented 1 year ago

Thanks for the swift response @KalleOlaviNiemitalo seems like a duplicate of https://github.com/dotnet/csharplang/issues/739. Thanks. Will close the issue

KalleOlaviNiemitalo commented 1 year ago

maybe a new DoesNotReturnIfNull would also be helpful

NotNullAttribute on an input parameter already means that, if the function returns, then the compiler can assume that the argument was not null.

linkdotnet commented 1 year ago

True but not in the context of an exception (or whether we can continue the control flow after the method in question).