-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Annotate System.Data.{Odbc,OleDb} for nullability #39597
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
src/libraries/System.Data.Odbc/src/System/Data/Odbc/OdbcDataReader.cs
Outdated
Show resolved
Hide resolved
|
Tagging subscribers to this area: @roji, @ajcvickers |
|
@stephentoub @jeffhandley the build failures seem to be because System.Data.Odbc is being built for older TFMs (netfx, netstandard2.0) where nothing is annotated, so Debug.Assert isn't recognized (when building locally, presumably for .NET Core, there are no errors/warnings). Nullability warnings/errors should probably be disabled for older TFMs here, right? |
I'm not sure myself. @ericstj, do you know? |
jeffhandley
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'm at 37/200 files viewed. So far so good. And thanks for fixing the spelling errors in comments!
src/libraries/Common/src/System/Data/ProviderBase/DbConnectionInternal.cs
Show resolved
Hide resolved
src/libraries/System.Data.Common/src/System/Data/Common/DbDataAdapter.cs
Show resolved
Hide resolved
Looks to me like folks are suppressing the warnings on other frameworks: runtime/src/libraries/Directory.Build.targets Lines 9 to 10 in 3f7202b
|
| for (int i = 0; i < restrictions.Length; ++i) | ||
| { | ||
| if (null != restrictions[i]) | ||
| if (restrictions[i] is { } restriction) |
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.
what does is { } mean?
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 is just a way to use pattern making to check if a value isn't null
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.
!= null or is not null would be better.
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.
!= null is the check being replaced, the problem is that since we're checking an array element, the compiler doesn't track the nullability status of that, and any additional reference is flagged again (that's why I made this change).
is not null is C# 9, right? Is it OK to use this already in runtime? If not, I can just use a local variable here instead (or replace this with is not null when that becomes available).
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.
FYI am going to merge as-is, but we can definitely replace these with the nicer is not null once we can use C# 9 here.
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.
There's a tiny benefit of capturing restriction, that will be realized more when using is not null.
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.
Sure, but neither { } nor is not null are necessary to achieve that:
if (restrictions[i] is string restriction)
{
...
}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.
Ah, yeah that'd be better indeed.
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.
The slight disadvantage of restrictions[i] is string restriction is that it's ambiguous with regards to whether we're checking that something isn't null, or that it's a string (as opposed to something else). FWIW Resharper/Rider warn about this.
I tried restrictions[i] is not null restriction, assuming that's how the C# 9 feature looks like, but it doesn't seem to compile. I'll just switch to restrictions[i] is string restriction for now as suggested.
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.
If you see it as a disadvantage, then just do the super simple thing:
foreach (string? restriction in restrictions)
{
if (restriction != null)
{
tmp[count++] = restriction;
}
}or
for (int i = 0; i < restrictions.Length; i++)
{
string? restriction = restrictions[i];
if (restriction != null)
{
tmp[count++] = restriction;
}
}or just suppress the warning:
for (int i = 0; i < restrictions.Length; i++)
{
if (restrictions[i] != null)
{
tmp[count++] = restrictions[i]!; // TODO-NULLABLE: Indexer nullability tracked (https://github.com/dotnet/roslyn/issues/34644)
}
}as we do in dozens of other places in dotnet/runtime... the more we work around it, the less likely it'll be the compiler "fixes" it.
cc: @cston
Not everything needs to use fancy syntax.
src/libraries/System.Data.Odbc/src/System/Data/Odbc/OdbcConnectionOpen.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Data.Odbc/src/System/Data/Odbc/OdbcDataReader.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Data.Odbc/src/System/Data/Odbc/OdbcDataReader.cs
Outdated
Show resolved
Hide resolved
| public override long GetBytes(int ordinal, long dataIndex, byte[]? buffer, int bufferIndex, int length) { throw null; } | ||
| public override char GetChar(int ordinal) { throw null; } | ||
| public override long GetChars(int ordinal, long dataIndex, char[] buffer, int bufferIndex, int length) { throw null; } | ||
| public override long GetChars(int ordinal, long dataIndex, char[]? buffer, int bufferIndex, int length) { throw null; } |
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.
is null buffer actually allowed or is it only for zero length?
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.
A null buffer makes the method just return the number of characters in the column, without returning it in any way (this is even in the docs... doesn't happen that often in System.Data :)).
|
I'm at 65/120 and have not seen anything blocking so far - my eyes got a bit blurry with question marks flying so will likely not finish today. The only comment is to replace all |
|
@ericstj (or anyone else) any idea about the nullability errors in the build? It's odd that they're only in that one config, and I don't get them when building locally... |
The reason we suppress nullability warnings in runtime/src/libraries/Directory.Build.targets Lines 9 to 10 in 3f7202b
Debug.Assert, which means if you have code like Debug.Assert(foo != null); foo.Blah();, without the [DoesNotReturnIf(false)] attribute on the assert, the compiler doesn't know that foo.Blah() is valid and warns that foo might be null. So, the most likely cause here is this library is building against a target that is not yet included in that Directory.Build.targets exclusion, and the fix would be to extend those conditions to make sure it's included.
|
|
Are you doing an We should probably just change the condition on nowarn to suppress on |
|
I went ahead and pushed a commit to suppress nullable warnings on all old netcoreapp frameworks as I suggested. |
|
Thanks @ericstj! |
Sure thing! @krwq @jeffhandley I think this is still pending review of annotations. |
jeffhandley
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'm at 80/121 files (although I started moving bottom up here recently). Will keep going tomorrow.
src/libraries/System.Data.Odbc/src/System/Data/Odbc/OdbcConnection.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Data.Odbc/src/System/Data/Odbc/OdbcConnectionHelper.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Data.Odbc/src/System/Data/Odbc/OdbcParameterHelper.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Data.OleDb/src/System/Data/ProviderBase/DbMetaDataFactory.cs
Outdated
Show resolved
Hide resolved
jeffhandley
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.
A bit more progress reviewing but still not done.
jeffhandley
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.
Finished reviewed. There were several places where you might want to use TODO-NULLABLE instead of TODO (following the pattern seen in other places in this PR). Just suggestions though.
I think what @ericstj spotted in DbMetaDataFactory.cs is a lurking regression. I don't know if there's existing test coverage that should have caught it though.
Nothing to actually annotated as it's a full facade assembly, all types have been moved to System.Data
ada6f2a to
b21b2a2
Compare
|
@jeffhandley @krwq and the others, thanks for the thorough reviewing, I've integrated all your comments. |
jeffhandley
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.
Thank you for all of the effort you put into this!!
Co-authored-by: Jeff Handley <jeffhandley@users.noreply.github.com>
* Annotate System.Data.Odbc for nullability * Annotate System.Data.OleDb for nullability * Suppress nullable warnings on netcoreapp < 3.0 * Mark System.Data.DataSetExtensions as null-annotated * Fix null-check bug in System.Data.OleDb
/cc @jeffhandley @ajcvickers