dotnet / roslyn

The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.
https://docs.microsoft.com/dotnet/csharp/roslyn-sdk/
MIT License
19.04k stars 4.03k forks source link

Deconstructing a ValueTuple containing nullable reference types result in the nullability annotation being lost #39732

Closed Gnbrkm41 closed 4 years ago

Gnbrkm41 commented 4 years ago

Related: https://github.com/dotnet/corefx/issues/42463

Version Used: VS2019 Community Preview 16.4 P4 (Compiler version: '3.4.0-beta3-19554-05 (0c5378aa)'. Language version: default.). Also reproduced on the LINQPad 6.4.4 (Compiler version: '3.3.1-beta4-19462-11 (66a912c9)'. Language version: preview.)

Steps to Reproduce:

  1. Create a ValueTuple containing any number of nullable reference types
  2. Deconstruct and declare new local variables with the deconstruction syntax
  3. Check the type of the nullable reference types
    
    #nullable enable
    using System;

namespace ConsoleApp19 { class Program { static void Main(string[] args) { (int? ayy, string? lmao) tuple = (42, "ayy lmao"); var (ayy, lmao) = tuple; // Alternatively: // (int? ayy, string? lmao) = tuple; } } }



**Expected Behavior**:
Nullability annotations should be preserved.
**Actual Behavior**:
Nullablilty annotations are lost.

![image](https://user-images.githubusercontent.com/42944058/68453896-36dc7e00-023a-11ea-8b76-b3bd86dad132.png)
IntelliSense shows that the deconstructed `lmao` variable is non-nullable; Not only that this shows up like this, [A VS plugin I'm using that shows the actual type of any implicitly typed variables](https://marketplace.visualstudio.com/items?itemName=AlexanderGayko.VarAdorner) also suggest that the second element is non-nullable;
![image](https://user-images.githubusercontent.com/42944058/68454088-e9acdc00-023a-11ea-986a-131ec30cf22d.png)
In addition, using the suggested fix for IDE0008 (`Use explicit type instead of 'var'`) also suggests that it is non-nullable:
![image](https://user-images.githubusercontent.com/42944058/68454149-18c34d80-023b-11ea-9c00-e622278b6012.png)

This does not happen if I'm not deconstructing the tuple:
![image](https://user-images.githubusercontent.com/42944058/68454204-3db7c080-023b-11ea-8c19-abfd6bc07b5b.png)
CyrusNajmabadi commented 4 years ago

I think this is by design (@jcouv to confirm). You're assigning "ayy lmao", so the value isn't actually null. If you actually use null, you'll see this as string?

            (int? ayy, string? lmao) tuple = (42, null);
            var (ayy, lmao) = tuple;

image