dotnet/roslyn

`IDE0063` fix introduces `CS8648` in presence of `goto` statements

開放

#39,637 建立於 2019年11月1日

 (3 則留言) (0 個反應) (0 位負責人)C# (4,257 個分叉)batch import
Area-CompilersBugFeature - IDE0063IDE-CodeStylehelp wanted

倉庫指標

星標
 (20,414 顆星)
PR 合併指標
 (平均合併 6天 17小時) (30 天內合併 256 個 PR)

描述

Version Used: I think 3.4.0-beta2-19504-06 as C# Interactive shows that version.

VS is 16.4.0 Preview 2.0.

<TargetFramework> is netcoreapp3.1 so I believe I am using <LangVersion>Preview</LangVersion> implicitly.

Steps to Reproduce:

The code below will show the fix suggestion /*IDE0063*/ and the code after applying the IDE0063 fix at the location shown with error /*CS8648*/.

  • IDE0063 Use simple 'using' statement
  • CS8648 A goto cannot jump to a location after a using declaration

The crux appears to be that there are two statements blocks nested, with the nested one bing a using statement. The first isn't showing IDE0063 whereas the second does offer the fix, which breaks the code when applied.

Expected Behavior: The fix suggestion does not appear.

Or in fact, even if there is code between the two } such that the finally blocks are apart, applying the fix would in fact have to put the finalizer for the simple using statement at the end of the block it is in, which is the finalizer position of the first using statement in the code below. So one could argue whether the code below in both forms should produce the exact same syntax tree end hence both compile without error.

On top of that, my understanding of the feature is that any block in which the simple using statement appears would become protected by the finalizer, even if there is just an if block or even just { ... } without any construct accompanying it. And indeed, if I remove the exact text using (var d = new Disposable()) (but leave the brace-open) in the IDE0063_After code, the goto preceding the brace-open does not show CS8648.

So:

Really Expected Behavior Whether I accept the fix or not, the code compiles and CS8648 does not appear.

Actual Behavior: The fix suggestion, even before it is applied - in the preview, produces error CS8648 "A goto cannot jump to a location after a using declaration".

Code

struct Disposable : IDisposable { public void Dispose() { } }
class IDE0063_Before
{
    static int Main(string[] args) {
        var errorLevel = 0;
        if (args.Length == 0) goto Fail;
        using (var d = new Disposable()) {
            if (int.TryParse(args[0], out errorLevel)) goto Fail;
            /*IDE0063*/
            using (var e = new Disposable()) {
                foreach (var arg in args)
                    if (int.TryParse(arg, out errorLevel)) goto Fail;
            }
        }
        return errorLevel;
    Fail:
        errorLevel = default;
        return errorLevel;
    }
}
class IDE0063_After
{
    static int NotMain(string[] args) {
        var errorLevel = 0;
        if (args.Length == 0) goto Fail;
        using (var d = new Disposable()) {
            if (int.TryParse(args[0], out errorLevel)) /*CS8648*/ goto Fail;
            using var e = new Disposable();
            foreach (var arg in args)
                if (int.TryParse(arg, out errorLevel)) goto Fail;
        }
        return errorLevel;
    Fail:
        errorLevel = default;
        return errorLevel;
    }
}

貢獻者指南