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

Disallow converted string as default argument value #59806

Merged
merged 3 commits into from
Mar 1, 2022

Conversation

jcouv
Copy link
Member

@jcouv jcouv commented Feb 28, 2022

Fixes #59789

See relevant section of the spec.
Note, this is aligning the behavior with that of const, which makes sense. In our constant folding logic (FoldConstantConversion), only null remains a constant when subjected to a reference conversion. So we produce a diagnostic for const scenario in GetAndValidateConstantValue.

@jcouv jcouv self-assigned this Feb 28, 2022
@jcouv jcouv added this to the 17.2 milestone Feb 28, 2022
@jcouv jcouv marked this pull request as ready for review February 28, 2022 18:35
@jcouv jcouv requested a review from a team as a code owner February 28, 2022 18:35
@@ -624,12 +624,11 @@ private static void CheckParameterModifiers(BaseParameterSyntax parameter, Bindi
hasErrors = true;
}
else if (conversion.IsReference &&
(parameterType.SpecialType == SpecialType.System_Object || parameterType.Kind == SymbolKind.DynamicType) &&
Copy link
Member

Choose a reason for hiding this comment

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

Have you gone back in the history to find out why this line was added? This seems extremely deliberate, so I want to have a good understanding of why it was there in the first place.

Copy link
Member Author

Choose a reason for hiding this comment

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

This line dates from Pilchie's "Hello World" commit.
I should have copied the info here from the bug thread, but the native compiler correctly produced an error:
test.cs(6,37): error CS1763: 'x' is of type 'System.Collections.Generic.IEnumerable<char>'. A default parameter value of a reference type other than string can only be initialized with null

Copy link
Contributor

Choose a reason for hiding this comment

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

The whole block is from the Roslyn.Says("Hello World"); commit. Is there somewhere internal that should be searched as well?

Copy link
Member

Choose a reason for hiding this comment

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

This line dates from Pilchie's "Hello World" commit.

I guessed so, but I think this is something I would like information from TFS on. Sorry 🙂.

Copy link
Member

Choose a reason for hiding this comment

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

Ok, so @jcouv and I did some spelunking through many layers of TFS to find that this was added by Eric at least a decade ago. Unless @ericlippert remembers why this originally only checked if the parameter type was object and wants to chime in here, I'd say I'm good with the change, provided VS still builds. This is one I think we want a validation PR for.

Copy link
Contributor

Choose a reason for hiding this comment

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

What is the native compiler behavior?

Copy link
Member

Choose a reason for hiding this comment

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

What is the native compiler behavior?

@AlekseyTs Julien tested it in the bug itself. It was an error: #59789 (comment)

Choose a reason for hiding this comment

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

Good spelunking. I definitely wrote that line of code, and I have no memory of why I added that extra check. I concur that it is unnecessary.

@RikkiGibson
Copy link
Contributor

I think the change here brings us into conformance with the spec.

Currently, the compiler does something certainly wrong here: it gives no error, and silently uses 'null' as the default argument at call sites. Unless something critical is uncovered, I think we should just fix it and bring ourselves into alignment with the native compiler.

@RikkiGibson
Copy link
Contributor

RikkiGibson commented Feb 28, 2022

@tannergooding raised an interesting scenario in LDM that might be broken by this PR. SharpLab

I think in general we don't want implicit default arguments to involve calling user-defined operators such as implicit operator ReadOnlySpan<char>(string)--the specification disallows it.

@tannergooding
Copy link
Member

raised an interesting scenario in LDM that might be broken by this PR

Notably I'm not sure this will break it. This is changing the ability to declare T x = const where T has some implicit conversion from const

This is different from the relevant IL metadata being present and the compiler interpreting that as given.

Would be nice/good to have a test validating things though.

@RikkiGibson
Copy link
Contributor

The compiler is supposed to check the argument used in the DefaultParameterValueAttribute and give a diagnostic if it's not compatible. When such an attribute is found in metadata, for example, though, the compiler is allowed to silently use a null default argument.

@RikkiGibson
Copy link
Contributor

Oh my god. I just realized this optional parameter is not even at the end of the parameter list. What. And that we pretty much only disallow the attribute argument if conversion doesn't exist at all. SharpLab

What have we done, Tanner..

@RikkiGibson RikkiGibson self-assigned this Feb 28, 2022
@jcouv jcouv requested a review from 333fred February 28, 2022 20:37
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.

LGTM (commit 1), provided the val build passes and we update the breaking changes doc.

@jcouv
Copy link
Member Author

jcouv commented Mar 1, 2022

Started val build. (instructions for later reference)

@jcouv
Copy link
Member Author

jcouv commented Mar 1, 2022

The val build succeeded. It shows the correct PR number and commit SHA:
image

@jcouv jcouv enabled auto-merge (squash) March 1, 2022 04:56
@RikkiGibson
Copy link
Contributor

It looks like we succeeded at creating a VS insertion, but you'll still have to click through and confirm that the insertion (i.e. pull request to VS) has passing checks.

@jcouv jcouv disabled auto-merge March 1, 2022 05:10
@jcouv
Copy link
Member Author

jcouv commented Mar 1, 2022

Let's sync tomorrow. Here's what I see for https://dev.azure.com/devdiv/DevDiv/_git/VS/pullrequest/382848
image

@RikkiGibson
Copy link
Contributor

Reviewed the val build this morning, all the checks we care about are green so we are good to go there.

@RikkiGibson RikkiGibson merged commit d07f2b1 into dotnet:main Mar 1, 2022
@ghost ghost modified the milestones: 17.2, Next Mar 1, 2022
@jcouv jcouv deleted the bad-default branch March 1, 2022 18:43
@@ -98,3 +98,11 @@ https://github.com/dotnet/roslyn/issues/57750
public S() { Y = 0; } // ok
}
```

7. <a name="7"></a>Before Visual Studio 17.2, the C# compiler would accept incorrect default argument values involving a reference conversion of a string constant, and would emit `null` as the constant value instead of the default value specified in source. In Visual Studio 17.2, this becomes an error. See [roslyn#59806](https://github.com/dotnet/roslyn/pull/59806).
Copy link
Member Author

Choose a reason for hiding this comment

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

FYI @BillWagner @dotnet/docs. New C# breaking change incoming in 17.2

Copy link
Member

Choose a reason for hiding this comment

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

docs change was merged yesterday: dotnet/docs#28498

@allisonchou allisonchou modified the milestones: Next, 17.2.P3 Mar 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Default parameters of interface type are silently set to null for string constants
8 participants