Roslyn: Consider representing nullable flow state as: MaybeNull, NotNull, or T

Created on 11 Sep 2019  Â·  5Comments  Â·  Source: dotnet/roslyn

Consider adding a distinct nullable flow state, T, to allow distinguishing "maybe null when the type allows null" from "maybe null even when type disallows null".
C# internal enum NullableFlowState : byte { NotNull, // not null T, // maybe null when type allows MaybeNull // maybe null even when type disallows }

Area-Compilers Investigating New Language Feature - Nullable Reference Types

Most helpful comment

This example just started giving me warnings in VS 16.4 Preview 2

C# [return: MaybeNull] public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dic, TKey key, TValue defaultValue = default) where TKey : notnull => dic.TryGetValue(key, out var value) ? value : defaultValue;

Results in warning CS8717: A member returning a [MaybeNull] value introduces a null value when 'TValue' is a non-nullable reference type

Would this allow the [MaybeNull] from TryGetValue to flow through?

All 5 comments

FYI for @jasonmalinowski

Even if we just add the third state, without adding a corresponding type/annotation for locals, some scenarios would be improved.
Here's one reported by Sam:

#nullable enable

using System;
using System.Diagnostics.CodeAnalysis;

public class C<T> {
    [MaybeNull] T value;
    public void M() {
        if (value is null)
            return;
    }
}

This example just started giving me warnings in VS 16.4 Preview 2

C# [return: MaybeNull] public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dic, TKey key, TValue defaultValue = default) where TKey : notnull => dic.TryGetValue(key, out var value) ? value : defaultValue;

Results in warning CS8717: A member returning a [MaybeNull] value introduces a null value when 'TValue' is a non-nullable reference type

Would this allow the [MaybeNull] from TryGetValue to flow through?

CS8717 feels subpar to me. The warning should follow the (mis)usage, not the declaration. As it stands, CS8717 only shows up on valid (even ideal) code.

void M<T>()
{
    var x = new Dictionary<int, T>();

    // CS8717 A member returning a [MaybeNull] value introduces a null value when 'TResult' is a
    // non-nullable reference type.
    //                        ↓
    if (x.TryGetValue(42, out var someValue))
    {
    }
}

FYI, this is super unpleasant. I honestly don't know how to write code in some cases that is actually NRT correct. I thought MaybeNull was intended for this, but @jcouv informs me that for the actual uninstantiated cases (i.e. while you're writing generic code), you're just SOL here :-/

Was this page helpful?
0 / 5 - 0 ratings