-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Do not treat Nullable
null value as a constant for the purpose of IL generation.
#64789
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need a bit of help to understand this fix (it seems in a very central location and surprising).
From what I can tell, the problem is only occurring when there is an identity conversion between the implicit user-defined conversion and the
null
literal.Below are the bound tree for nullable tuples scenario (broken) vs. nullable
int
scenario (works) for comparison.Looking at those two trees, I can see that there is an additional identity conversion in the tuples scenario. It's a conversion of
default
to type(int SomeInt, bool SomeBool)?
.Why does that conversion node have a constant value, but the child
default
node doesn't?#Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at the spec (constants), the identity conversion of
null
should be a constant. That suggests the conversion node is correct (hasconstantValueOpt
) but the default expression nodes are missingconstantValueOpt
. Should we file an issue on that?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because, strictly speaking, the original conversion node, created by initial binding, shouldn't have one either. In my opinion this an old bug in compiler's behavior, see #24380. Unfortunately, the presence of the constant value on the conversion was taken advantage of in implementation of some features (patterns, for example) and there was a resistance to get this cleaned up. Given the situation, various parts of the compiler have to compensate for that. For example, LocalRewriter has this code to ignore nullable constant values:
The proposed fix is essentially doing the same thing in IL generation. If we get consensus around fixing the #24380, we can do that during MQ milestone.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the clarification.
The link you shared might be incorrect though (seems like an unrelated merged PR).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The first link is correct, the second reference is missing zero at the end, I'll fix
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually disagree with this analysis and think that, according to the specification, values of a nullable type should never have a constant value. This applies to a nullable null, and to a nullable default value. I think I expressed the rationale behind this opinion in #24380.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reading the thread in #24380, I'm convinced. The allowed conversions for constants are enumerated, but the conversion of
null
to nullable value type (described here) isn't listed.Hopefully we have a special rule somewhere for default parameter values
void M(int? i = null)
, since this is not quite a constant.Then from an implementation perspective, the constant value (non-null
constantValueOpt
) indeed would be the root cause. I'm still okay with localized workaround for now. Thanks