-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Missing nullable warning in generic methods #35602
Comments
Can you tweak your code sample to remove the JsonConvert dependency by any chance? A standalone repro would be ideal. For instance, on sharplab. |
Hum, I tweaked your sample (replacing calls to |
The Is it normal that Roslyn doesn't care at all if we check if a reference is null and then return it after? Only the declared type is taken in account? |
If We're working on making this information more readily available in IDE/QuickInfo (likely for 16.2 release). |
Of topic but: is it possible to make it assume the worst on some external assemblies or classes? (all references can be null)
The code was using an old version of Newtonsoft.Json so it was very unlikely. That's why I wondered what kind a black magic was in place here.
Very cool! This is indeed a must have. Can we get that information with other tools for now? (like dotPeek) |
I modified the example to avoid the references to Newtonsoft.json but it does work as expected. So I'm not sure what triggers the issue. |
I couldn't reproduce my original problem but I tweaked it to highlight some issues explained in comments (see on sharplab): public static class JsonConvert
{
public static T DeserializeObject<T>() => default;
}
#nullable safeonly
// This class does get the two warnings correctly
class NullTestWithContraints
{
static void Print(object value) => value.ToString();
static T GetGeneric<T>() where T : class, new()
{
var possibleNullValue = JsonConvert.DeserializeObject<T>();
// Remark: If I comment this check I don't get anymore warnings => looks ok to me
if (possibleNullValue == null) {}
// Remark: If I replace this by possibleNullValue.ToString(); I don't get the next warning
// => doesn't look ok to me
Print(possibleNullValue);
return possibleNullValue;
}
}
// This class only gets one warning
class NullTestWithoutContraint
{
static void Print(object value) => value.ToString();
static T GetGeneric<T>()
{
var possibleNullValue = JsonConvert.DeserializeObject<T>();
// Remark: If I comment I still get the warning
// => doesn't look ok to me
if (possibleNullValue == null) {}
Print(possibleNullValue);
// This is the main issue. No warning here ?
// The only difference here is that in this case T can be a non reference-type
return possibleNullValue;
}
} |
If you have a non-null value, but do a "pure" null test on it (such as That said, maybe I misunderstood something. It would be easier if you distilled one or two scenarios that are unexpected for you, rather than mixing potentially well-behaved and misbehaved scenarios. Also, the name of your locals seem incorrect for current design (oblivious APIs produce non-null values).
It is not possible at the moment. This feature has many trade-offs and we're trying to find a good middle that allows existing projects to adopt the feature, as well as new projects. |
Sure I can detail the 3 weird behaviors I noticed in my example:
public static class JsonConvert
{
public static T DeserializeObject<T>() => default;
}
#nullable safeonly
class NullTestWithoutContraint
{
static void GetGeneric<T>()
{
var nonNullValue = JsonConvert.DeserializeObject<T>();
nonNullValue.ToString(); // Why do I a get a warning here?
}
} (see on sharplab)
public static class JsonConvert
{
public static T DeserializeObject<T>() => default;
}
#nullable safeonly
class NullTestWithoutContraint
{
static T GetGeneric<T>()
{
var possibleNullValue = JsonConvert.DeserializeObject<T>();
if (possibleNullValue is null) {}
return possibleNullValue; // No warning here
}
} (see on sharplab)
#nullable safeonly
class NullTest
{
static void Print(object value) => value.ToString();
static string Test()
{
var possibleNullValue = default(string);
if (possibleNullValue == null) {}
possibleNullValue.ToString();
return possibleNullValue; // <= No warning here
}
} (see on sharplab) |
|
|
Also is there a way to add a constraint to say that T is a nullable reference? |
I'm sure we'll adjust diagnostics based on preview feedback and dogfooding experience. This is useful feedback.
You can already do it with |
Note, I updated the original post with the salient scenario (2). |
Version Used:
[email protected]
Steps to Reproduce:
Expected Behavior:
possibleNullValue
.possibleNullValue
asking to return a nullable.Actual Behavior:
I only have a "possible null reference" warning on the last
Check(value)
(in the generic method). In fact I don't think the compiler really knowspossibleNullValue
can really be null so it looks like a bug to me (even if the warning is totally valid).Adding the code error here so that people don't have to open the .zip:
[jcouv updated:]
I think we've narrowed down to the most questionable/suspicious scenario:
(see on sharplab)
The text was updated successfully, but these errors were encountered: