Skip to content

Fix analysis of parameter default values#49009

Merged
RikkiGibson merged 13 commits intodotnet:masterfrom
RikkiGibson:fix-47352
Nov 9, 2020
Merged

Fix analysis of parameter default values#49009
RikkiGibson merged 13 commits intodotnet:masterfrom
RikkiGibson:fix-47352

Conversation

@RikkiGibson
Copy link
Member

@RikkiGibson RikkiGibson commented Oct 29, 2020

Closes #48844
Closes #48847
Closes #48848
(note that these are really just 3 test cases, and expected behavior stated in the issues is not met by this PR. We changed the expectation as described in nullable-parameter-default-value-analysis.md)

Related to #47352

Summary: parameter default values no longer affect initial state. A parameter default value which is incompatible with the parameter type is always a safety warning.

@RikkiGibson RikkiGibson requested a review from a team as a code owner October 29, 2020 00:15
ImmutableArray<LocalSymbol>.Empty,
// note that if the parameter type conflicts with the default value from attributes,
// we will just get a bad constant value above and return early.
new BoundLiteral(parameterSyntax, DefaultValueFromAttributes, Type));
Copy link
Contributor

Choose a reason for hiding this comment

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

DefaultValueFromAttributes [](start = 50, length = 26)

defaultValue

@RikkiGibson
Copy link
Member Author

RikkiGibson commented Oct 29, 2020

Oh, we introduced new warnings in Roslyn :)

src/Workspaces/Core/Portable/Shared/TestHooks/IAsynchronousOperationListener.cs(11,67): error CS8625: Cannot convert null literal to non-nullable reference type.

IAsyncToken BeginAsyncOperation(string name, object tag = null, [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0);

@RikkiGibson RikkiGibson requested a review from a team as a code owner October 29, 2020 20:46
@RikkiGibson
Copy link
Member Author

@dotnet/roslyn-compiler Please review

@jcouv jcouv added the Feature - Nullable Reference Types Nullable Reference Types label Nov 4, 2020
@RikkiGibson
Copy link
Member Author

@dotnet/roslyn-compiler Please review

@RikkiGibson
Copy link
Member Author

@dotnet/roslyn-compiler Please review

Copy link
Member

@333fred 333fred left a comment

Choose a reason for hiding this comment

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

Done review pass (commit 12)

{
if (binder is not null && parameterEqualsValue is not null && !_lazyDefaultSyntaxValue.IsBad)
{
NullableWalker.AnalyzeIfNeeded(binder, parameterEqualsValue, diagnostics);
Copy link
Member

Choose a reason for hiding this comment

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

Why are we analyzing here and below?

Copy link
Member Author

Choose a reason for hiding this comment

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

In this implementation, _lazyDefaultSyntaxValue must be initialized on parameters before performing nullable analysis to avoid a stack overflow.

In my subsequent PR #49186 I modify DefaultSyntaxValue to return ConstantValue.Unset if we have not finished initializing the default value, for example when binding the default argument to F() in void F(object param = F()) { }.

Given that, we could clean this up to move analysis of the syntax value to within MakeDefaultExpression and move analysis of the attribute value to perhaps GetAttributesBag on this symbol in a follow-up.


private void NullableAnalyzeParameterDefaultValueFromAttributes(DiagnosticBag diagnostics)
{
var defaultValue = DefaultValueFromAttributes;
Copy link
Member

Choose a reason for hiding this comment

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

Consider skipping all this work if we don't need to do nullable analysis.

Copy link
Member Author

Choose a reason for hiding this comment

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

Happy to do this in the follow-up at the same time as moving this check to a more appropriate spot.

// we will just get a bad constant value above and return early.
new BoundLiteral(parameterSyntax, defaultValue, Type));

NullableWalker.AnalyzeIfNeeded(binder, parameterEqualsValue, diagnostics);
Copy link
Member

Choose a reason for hiding this comment

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

How is this information getting to the semantic model? IE, hovering over the default keyword for a NRT should have a nullable state of MaybeNull, are there tests for this?

Copy link
Member Author

Choose a reason for hiding this comment

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

I actually have no idea, but I will try to add some tests that I think cover this gap for this as well as for attributes which use a similar approach for nullable analysis.

Diagnostic(ErrorCode.WRN_DefaultValueForUnconsumedLocation, "x").WithArguments("x").WithLocation(6, 34),
// (6,38): warning CS8625: Cannot convert null literal to non-nullable reference type.
// static partial void G(object x = null, object? y = null) { }
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(6, 38),
Copy link
Member

Choose a reason for hiding this comment

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

I assume you have a test insertion, since we're adding new warnings?

Copy link
Member Author

Choose a reason for hiding this comment

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

I kicked it off now, thanks. I'll link the insertion once it gets created.

Copy link
Member Author

Choose a reason for hiding this comment

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

https://devdiv.visualstudio.com/DevDiv/_git/VS/pullrequest/286574

Looks like there are 8 new nullable warnings. Some require just adding ? to a CallerMemberName parameter. The rest probably require adding a ! e.g. M<T>(T defaultValue = default!), because the project targets C# 8 and nullability attributes don't appear to be available.

@RikkiGibson RikkiGibson merged commit 0f21966 into dotnet:master Nov 9, 2020
@ghost ghost added this to the Next milestone Nov 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

6 participants