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.05k stars 4.04k forks source link

Intellisense triggers ArgumentException when a variable is a different type depending on #if when nullable is enabled #45533

Closed vsfeedback closed 2 weeks ago

vsfeedback commented 4 years ago

This issue has been moved from a ticket on Developer Community.


So, let's say I'm targeting both .Net Standard 2.0 and .Net Standard 2.1 in a particular project so that I can use spans in the latter. I am implementing a particular method like this:

#if NETSTANDARD2_1
    ReadOnlySpan<char> value;
#else
    string value;
#endif

#nullable enable
    value = whatever();
    for (int i = 0; i < value.Length; i++)
    {
        ...
    }

IntelliSense crashes with an ArgumentException if I move the mouse over value or value.Length when all of the conditions are true:

  1. It's outside of the #if block (that is, it's in a scope in which there's any ambiguity as to whether it's a string or a ReadOnlySpan<char>,
  2. the current project is set to one in which value is a span (or Memory, or possibly other ref structs, etc), and
  3. nullable reference types are enabled.

This also happens with other type parameters, i.e. byte[]/ReadOnlySpan<byte> and suchlike.

(Also, if I access value. Length when either condition 2 or 3 is not all true, the IntelliSense hover reports value as a string and value. Length as ReadOnlySpan<char>. Length.)

Two obvious workarounds: either 1. disable #nullable in these sorts of scopes, or 2. switch the current project to one where it's not a ref struct.


Original Comments

Visual Studio Feedback System on 6/28/2020, 01:08 AM:

We have directed your feedback to the appropriate engineering team for further evaluation. The team will review the feedback and notify you about the next steps.


Original Solutions

(no solutions)

sharwell commented 4 years ago

Here's the stack trace of the exception:

Syntax node is not within syntax tree
   at Microsoft.CodeAnalysis.CSharp.CSharpSemanticModel.CheckSyntaxNode(CSharpSyntaxNode syntax)
   at Microsoft.CodeAnalysis.CSharp.CSharpSemanticModel.GetSymbolInfo(ExpressionSyntax expression, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.CSharp.CSharpSemanticModel.GetSymbolInfoFromNode(SyntaxNode node, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.CSharp.CSharpSemanticModel.GetSymbolInfoCore(SyntaxNode node, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.CSharp.QuickInfo.CSharpSemanticQuickInfoProvider.TryGetNullabilityAnalysis(Workspace workspace, SemanticModel semanticModel, SyntaxToken token, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.QuickInfo.CommonSemanticQuickInfoProvider.<CreateContentAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.CodeAnalysis.QuickInfo.CommonSemanticQuickInfoProvider.<BuildQuickInfoAsync>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.CodeAnalysis.QuickInfo.CommonQuickInfoProvider.<GetQuickInfoAsync>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.CodeAnalysis.QuickInfo.CommonQuickInfoProvider.<GetQuickInfoAsync>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.CodeAnalysis.QuickInfo.QuickInfoServiceWithProviders.<GetQuickInfoAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.VisualStudio.Telemetry.WindowsErrorReporting.WatsonReport.GetClrWatsonExceptionInfo(Exception exceptionObject)
DizzyHSlightlyVoided commented 4 years ago

Workaround 3 is of course to add the System.Memory NuGet package, which includes spans for pre-.Net Standard 2.0 ...

333fred commented 3 years ago

I have not been able to reproduce the crash in either 16.10 internal preview or in 16.9 P3. However, I can reproduce the issue where quickinfo shows information from the wrong TFM, and if the syntax node from the wrong TFM is sent to a later stage in the compiler pipeline I would expect a failure like the one in the OP, so I doubt that this is actually fixed. Assigning this to the IDE to investigate why wrong TFM is informing quick info. image

My repro sample:

using System;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
#if NETCOREAPP3_1
            ReadOnlySpan<char> value;
#else
            string value;
#endif

#nullable enable
            value = whatever();

            Console.WriteLine("Hello World!");

            for (int i = 0; i < value.Length; i++)
            {

            }
        }

        static
#if NETCOREAPP3_1
            ReadOnlySpan<char>
#else
            string
#endif
            whatever() => throw null!;
    }
}
<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFrameworks>netcoreapp3.1;netstandard2.0</TargetFrameworks>
        <LangVersion>8.0</LangVersion>
    </PropertyGroup>

</Project>
333fred commented 3 years ago

(And note that, while it's in the OP, #nullable enable has nothing to do with the bug AFAICT).

CyrusNajmabadi commented 2 weeks ago

Unable to repro this either.