Skip to content

Conversation

@jcouv
Copy link
Member

@jcouv jcouv commented Jun 24, 2019

Part of #35816 (work items for attributes)

@jcouv jcouv added this to the 16.2.P4 milestone Jun 24, 2019
@jcouv jcouv requested a review from a team as a code owner June 24, 2019 14:31
@jcouv jcouv self-assigned this Jun 24, 2019
private const int HasDisallowNullAttribute = 0x1 << 0;
private const int HasAllowNullAttribute = 0x1 << 1;
private const int HasMaybeNullAttribute = 0x1 << 2;
private const int HasNotNullAttribute = 0x1 << 3;
Copy link
Contributor

@cston cston Jun 24, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handling individual bits here is not necessary since FlowAnalysisAnnotations is already stored as a set of bits (see PEParameterSymbol.PackedFlags). #ByDesign

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PEParameterSymbol can store all the possible annotations, but here we only need to store only four, which are not even contiguous (see below). So I think we have to deal with individual bits/flags.

    [Flags]
    internal enum FlowAnalysisAnnotations
    {
        None = 0,
        AllowNull = 1 << 0,
        DisallowNull = 1 << 1,
        MaybeNullWhenTrue = 1 << 2,
        MaybeNullWhenFalse = 1 << 3,
        MaybeNull = MaybeNullWhenTrue | MaybeNullWhenFalse,
        NotNullWhenTrue = 1 << 4,
        NotNullWhenFalse = 1 << 5,
        NotNull = NotNullWhenTrue | NotNullWhenFalse,
        AssertsTrue = 1 << 6,
        AssertsFalse = 1 << 7,
    }

In reply to: 296767023 [](ancestors = 296767023)

static PackedFlags()
{
// Verify a few things about the values we combine into flags. This way, if they ever
// change, this will get hit and you will know you have to update this type as well.
Copy link
Contributor

@cston cston Jun 24, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider simplifying or eliminating this comment. In #36152, all similar comments have been changed to "Verify masks are sufficient for values." #Resolved

var source = @"
class D
{
static void M1<T>(T t1)
Copy link
Contributor

@cston cston Jun 25, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

T is not used. #Resolved

new COpen<T?>().f1 = t5;
new CStruct<T>().f5 = t5;
}
}";
Copy link
Contributor

@cston cston Jun 25, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider testing:

static void M6<T>([MaybeNull]T t6) where T : class
{
    new CClass<T>().f2 = t6;
}
static void M7<T>([NotNull]T? t7) where T : class
{
    new CClass<T>().f2 = t7;
}
...
``` #Resolved

#if DEBUG
static PackedFlags()
{
Debug.Assert(EnumUtilities.ContainsAllValues<FlowAnalysisAnnotations>(0xFF));
Copy link
Contributor

@cston cston Jun 25, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assert seems unrelated to the number of bits stored. #Resolved

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd kept the assertion to alert us if the enum changes, so that we consider adding handling here. That said, that seems superfluous, so I'll remove.


In reply to: 296972213 [](ancestors = 296972213)

}
public class CClass<TClass> where TClass : class
{
[MaybeNull]public TClass f2 = null!;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of scope, but I wonder how common it will be for people to misuse the attributes like this.

I think any usage of [MaybeNull] on a non-annotated reference type is probably wrong. The correct attribute usage would probably be to annotate as nullable, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this specific case, it seems okay to use the [MaybeNull]. That indicates that you could get a null out, but would be disallowed to put a null in.
I don't think that's very useful, but it is not strictly equivalent to saying TClass? f2 = null;

}
}

public abstract FlowAnalysisAnnotations FlowAnalysisAnnotations { get; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This name was pretty confusing for me at first. It doesn't really say anything about nullable or that it's only about the attributes, not ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only represents the annotations from user-specified attributes. I agree this name is a bit confusing (we have annotations like ? and flow analysis annotations like [DisallowNull]). I'll think about this for a subsequent PR.
Thanks

@jcouv
Copy link
Member Author

jcouv commented Jun 26, 2019

I'll hold this PR until either #36784 (fix for metadata loading on simple value types) or #36787 (reverting third metadata optimization) is in, to minimize the risk of conflict.
Those other PRs will not make the snap anyways. So this one can move forward.

@jcouv jcouv added the Blocked label Jun 26, 2019
@jcouv jcouv merged commit 0cd024c into dotnet:master Jun 26, 2019
@jcouv jcouv deleted the attr-fields branch June 26, 2019 18:40
@jcouv jcouv removed the Blocked label Jun 26, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants