Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Annotate ChangeTracking for nullability #24261

Merged
1 commit merged into from
Feb 26, 2021
Merged

Annotate ChangeTracking for nullability #24261

1 commit merged into from
Feb 26, 2021

Conversation

smitpatel
Copy link
Contributor

Part of #19007

@smitpatel smitpatel marked this pull request as ready for review February 24, 2021 21:53
roji
roji previously requested changes Feb 25, 2021
src/EFCore/ChangeTracking/ChangeTracker.cs Show resolved Hide resolved
src/EFCore/ChangeTracking/EntityEntryGraphNode.cs Outdated Show resolved Hide resolved
src/EFCore/ChangeTracking/Internal/ArrayPropertyValues.cs Outdated Show resolved Hide resolved
src/EFCore/ChangeTracking/PropertyEntry`.cs Outdated Show resolved Hide resolved
src/EFCore/ChangeTracking/PropertyValues.cs Outdated Show resolved Hide resolved
@@ -158,7 +160,7 @@ public virtual IEntityType EntityType
/// <param name="propertyName"> The property name. </param>
/// <param name="value"> The property value if any. </param>
/// <returns> True if the property exists, otherwise false. </returns>
public virtual bool TryGetValue<TValue>([NotNull] string propertyName, out TValue value)
public virtual bool TryGetValue<TValue>([NotNull] string propertyName, out TValue? value)
Copy link
Member

Choose a reason for hiding this comment

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

Probably [NotNullWhen(true)]

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But the value can be null even when true

Copy link
Member

Choose a reason for hiding this comment

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

It's the same logic as with GetValue above (or with ReadShadowValue), i.e. whether the user calls TryGetValue<string> or TryGetValue<string?>`. We should make a global decision on that and apply everywhere.

Copy link
Member

Choose a reason for hiding this comment

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

I think this is still left, since we made the decision to have GetValue return TValue and not TValue?.

src/EFCore/ChangeTracking/ReferenceEntry`.cs Outdated Show resolved Hide resolved
src/EFCore/Update/IUpdateEntry.cs Outdated Show resolved Hide resolved
@smitpatel smitpatel force-pushed the smit/MakeShayHappy branch 2 times, most recently from 563503a to dba8ce0 Compare February 25, 2021 23:35
@ghost
Copy link

ghost commented Feb 25, 2021

Hello @smitpatel!

Because this pull request has the auto-merge label, I will be glad to assist with helping to merge this pull request once all check-in policies pass.

p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (@msftbot) and give me an instruction to get started! Learn more here.

@ghost
Copy link

ghost commented Feb 25, 2021

Apologies, while this PR appears ready to be merged, I've been configured to only merge when all checks have explicitly passed. The following integrations have not reported any progress on their checks and are blocking auto-merge:

  1. Azure Pipelines

These integrations are possibly never going to report a check, and unblocking auto-merge likely requires a human being to update my configuration to exempt these integrations from requiring a passing check.

Give feedback on this
From the bot dev team

We've tried to tune the bot such that it posts a comment like this only when auto-merge is blocked for exceptional, non-intuitive reasons. When the bot's auto-merge capability is properly configured, auto-merge should operate as you would intuitively expect and you should not see any spurious comments.

Please reach out to us at [email protected] to provide feedback if you believe you're seeing this comment appear spuriously. Please note that we usually are unable to update your bot configuration on your team's behalf, but we're happy to help you identify your bot admin.

{
return null;
return default!;
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't this method return object[]? (and possibly banged at relevant call sites)? Though as long as it's correct, it's just a private function so no big deal.

small nit: I (now) usually use default! only in generic contexts. In reference type contexts like this one, I tend to use null! for more clarity.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Long chain.
So basically this implements PrincipalKeyValueFactory<object[]> hence type becomes non-nullable. The reason for T = object[] because it is used as dependents map which uses dict underneath which cannot use nullable type as key. So while it is default! it shouldn't hit the code path here.

@@ -67,7 +69,7 @@ public void RemoveFromCollection(IPropertyBase propertyBase, object removedEntit
var index = propertyBase.GetRelationshipIndex();
if (index != -1)
{
((HashSet<object>)_values[index])?.Remove(removedEntity);
((HashSet<object>)_values[index]!)?.Remove(removedEntity);
Copy link
Member

Choose a reason for hiding this comment

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

If you want the runtime check, remove the bang; if we know it should never be null, remove the question mark.

@@ -32,9 +34,9 @@ public bool TryGetValue(int index, out object value)
}

public T GetValue<T>(int index)
=> IsEmpty ? default : _values.GetValue<T>(index);
=> IsEmpty ? default! : _values.GetValue<T>(index);
Copy link
Member

Choose a reason for hiding this comment

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

This could be a case where it's more correct to return T?, since there's an additional Empty state. Is the user expected to know before calling this whether it's empty or not? If not, we probably want to force them to deal with the Empty state.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The way whole T of GetValue flows, this shouldn't be invoked with non-null type if it can be empty. It is same as we returning T from other places, if you ask for wrong nullability it will throw exception. default! throws exception for us. @ajcvickers - Thoughts?

src/EFCore/ChangeTracking/PropertyEntry`.cs Show resolved Hide resolved
src/EFCore/ChangeTracking/EntityEntryGraphNode.cs Outdated Show resolved Hide resolved
Copy link
Member

@roji roji left a comment

Choose a reason for hiding this comment

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

Looks almost perfect, see comments below.

@ghost ghost merged commit 9b252d8 into main Feb 26, 2021
@ghost ghost deleted the smit/MakeShayHappy branch February 26, 2021 09:28
@roji
Copy link
Member

roji commented Feb 26, 2021

May bad, forgot to remove auto-merge, sorry.

@roji roji linked an issue Mar 1, 2021 that may be closed by this pull request
23 tasks
roji added a commit that referenced this pull request Mar 16, 2021
roji added a commit that referenced this pull request Mar 16, 2021
roji added a commit that referenced this pull request Mar 16, 2021
This pull request was closed.
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.

Annotate EF Core for nullable reference types
4 participants