-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Nullable Reference Types for main library #2041
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
Conversation
The tooling caught the GeoPosition?[] => GeoPosition[] regression - excellent!
Revising what the user experience is like with NRTs here.
| } | ||
| return i % 2 == 0 ? null : Task.CompletedTask; | ||
| // TODO: What the freaking hell was this ever trying to do? | ||
| return i % 2 == 0 ? null! : Task.CompletedTask; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I...wut?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cc @mgravell ^
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a test so... two scenarios for the price of one?? Maybe?
|
@slorello89 I'd love thoughts here anywhere, but specifically on return types (e.g. from IDatabase and IServer and async interfaces) as to what's nullable and if any strike you as incorrect. I know that's a big ask, but if you had the time to scroll those and give thoughts on any tweaks, I'd appreciate it! |
This removed the parent bits and just accepts a null case, code before this was likely an iteration that just didn't get all the way to simplest.
In prep for more PRs and easier reviews, turning a lot of the language features on that I've addressed as part of NRTs but doing further here while having to review all changes anyhow. These are minor, but align on styles.
slorello89
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @NickCraver,
I went through the rest of what was in here, had a couple of questions about things that were null and a few other minor comments.
There is an awful lot of what looks like code cleanup changes in the Wrapper classes.
I scrolled through the entirety of IDatabase and IServer, for potentially missing threads to pull on, I only found a few inconsistencies in there (my questions in IServer are fleshed out in the other comments.
But a few things in IDatabase:
- KeyRandom can return a null key if Redis is empty
- It looks Like the HashEntry[] result for
HashGetAllMIGHT be null? - theParsemethod in the ResultProcessor - looks like it can pull back a null array. - Is the result of
IdentifyEndpointpotentially null?
Overall looks really good, obviously, there are questions as to whether or not this would be a minor or major version revision for the library. Putting that aside, I don't think I saw anything that I would insist on changing.
Also: think it's missing release notes :)
There are things we're removing completing in 3.0 which means actually binary breaks potentially, vs. people opting into warnings as errors on a 2.x release - decision is to go with a minor here and embrace warnings as warnings. If you want to hard break on warnings (like our existing `[Obsolete(error = false)]` additions), so be it.
Return an empty array instead (key is already the null indicator - an empty array is good here).
If we can't parse a response, properly throw here and go not nullable.
slorello89
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1 weird comment that looks like it was probably an accidental copy/paste out of a different PR.
Otherwise, I think this looks pretty set.
I think calling this a Minor vs Major release is the right move, emitting warnings is fair in a minor IMO.
| return db; | ||
| } | ||
|
|
||
| /// <summary> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this comment seem like it was accidentally pasted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wooops, what the hell Nick?
slorello89
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 👍
mgravell
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've looked through this, focusing on the stuff under Interfaces (the primary public API), and it looks good to me. A few nice tweaks around Try etc. I'm not personally too concerned if we need to tweak some of the NRT annotations later, but: looks good to me. Nice job, sir.
| /// </summary> | ||
| public override string ToString() | ||
| { | ||
| if (toString != null) return toString; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❤️ you care!
To help in reviewing this, I've provided an overview to listen along while reviewing.
This is exploring what NRTs (nullable reference types) would look like on the main library. This covers the migration + test migration (to get a feel for what users would see). Highlights are:
nullcould have happened before to keep it non-nullable (e.g. forFireAndForgeton a fetch).RedisKey/RedisValue/friends arestring?which changes a lot of(string)casts.IConvertibleisobjectand notobject?and soRedisValueandRedisResultare...just lying. They can be null. I have no idea why the decision on not-nullable is the way it is.IConvertible.ToType, lying again.[return: NotNullIfNotNull("field")]doesn't work like you'd think onTask<T>/Task<T?>, so we have 2 versions ofExecuteAsynctrees for nullable vs. non-nullable (e.g. non-nullable default value provided, like with the arrays mentioned above).where T : defaulthere. Don't ask for details. Because I don't really understand why..IsNullOrEmpty()and.IsNullOrWhiteSpace()extensions are just easier due to lack of annotations on full framework.TryGetException? Don't want to make the 99.9% success case more expensive though.GetBridge(message)!, which isn't null ifcreateistrue, so maybe break this into 2 methods with nocreatearg, one of which isn't nullable? (TryGetBridgeisn't great because this is most often chained).