Skip to content
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

Fix extra warning for unused local function #47473

Merged
merged 3 commits into from
Sep 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1180,7 +1180,7 @@ public override BoundNode VisitCall(BoundCall node)
VisitReceiverBeforeCall(node.ReceiverOpt, node.Method);
VisitArgumentsBeforeCall(node.Arguments, node.ArgumentRefKindsOpt);

if (!callsAreOmitted && node.Method?.OriginalDefinition is LocalFunctionSymbol localFunc)
if (node.Method?.OriginalDefinition is LocalFunctionSymbol localFunc)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since node is actually a BoundCall, then we already know the local function is used. We want to visit it regardless it's conditionally omitted or not.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I worry that this change may be unsound (allowing accessing an unassigned variable). Please add a test for:

public class C 
{
    public void M() 
    {
        int i;
        local();
        i.ToString();
        
        [Conditional("DEBUG")]
        void local()
        {
           i = 1;   
        }
    }
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will be good to add this test. I believe it will produce the desired error on i.ToString() because we reset the definite assignment state after visiting the call when callsAreOmitted is true.

Copy link
Contributor

@RikkiGibson RikkiGibson Sep 7, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh wait. I forgot that we disallow non-static local functions from having ConditionalAttribute at all. We have specified that a local function must be static in order to be conditional.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we disallow non-static local functions from having ConditionalAttribute at all.

That saved some extra debugging 😄

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jcouv Please take another look at your convenience. I do not think there is a supported scenario involving capturing variables in a conditional local function.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good. That's great.
Can we update the test (LocalFunction_ConditionalAttributeDisallowed). We should be able to remove the #pragma warning.

{
VisitLocalFunctionUse(localFunc, node.Syntax, isCall: true);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5511,7 +5511,7 @@ static void validate(ModuleSymbol module)
}

[Fact]
public void StaticLocalFunction_ConditionalAttribute_Unreferenced()
public void StaticLocalFunction_ConditionalAttribute_NoUnreferencedWarning()
{
var source = @"
using System.Diagnostics;
Expand All @@ -5531,10 +5531,7 @@ static void local1()
}
}
";
CreateCompilation(source, parseOptions: TestOptions.Regular9).VerifyDiagnostics(
// (12,21): warning CS8321: The local function 'local1' is declared but never used
// static void local1()
Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "local1").WithArguments("local1").WithLocation(12, 21));
CreateCompilation(source, parseOptions: TestOptions.Regular9).VerifyDiagnostics();

CreateCompilation(source, parseOptions: TestOptions.Regular9.WithPreprocessorSymbols("DEBUG")).VerifyDiagnostics();
}
Expand Down