-
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
Dictionary expressions: remove PROTOTYPE comments #77876
Dictionary expressions: remove PROTOTYPE comments #77876
Conversation
@@ -907,8 +904,6 @@ private BoundCollectionExpression ConvertCollectionExpression( | |||
{ | |||
var analyzedArguments = AnalyzedArguments.GetInstance(); | |||
withElement.AddToArguments(analyzedArguments); | |||
// PROTOTYPE: If there are multiple with() elements, should with() elements after |
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.
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.
As long as the bad constructor calls say they have errors in the operation tree, this seems fine. That's just us giving the full information about what we think the code means.
@@ -1004,8 +997,6 @@ private BoundCollectionExpression ConvertCollectionExpression( | |||
if (collectionCreation is null) | |||
{ | |||
// Bind collection creation with no arguments. | |||
// PROTOTYPE: Should we require a factory method callable with no arguments even if arguments are provided |
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.
Tracked with an open question.
@@ -6631,8 +6631,6 @@ static BoundCall bindKeyOrValue(SyntaxNode syntax, BoundExpression expr, MethodS | |||
return new BoundCall( | |||
syntax, | |||
receiverOpt: expr, | |||
// PROTOTYPE: What is the correct value for receiver cloning? Test with expression element |
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.
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.
Were the indicated tests added? It wasn't clear to me why these accessors being on well-known type affects what value we should pass here.
It seems like existing places in the binder where False
is passed here, are taking care to ensure that the receiver is something we can take a reference to.
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.
Switched to calling ReceiverIsSubjectToCloning(expr, getMethod)
, to avoid hardcoding the value. However, expr
is a BoundValuePlaceholder
so ReceiverIsSubjectToCloning()
simply returns ThreeState.False
.
Should expr
be the original expression that the placeholder will be replaced with? cc @AlekseyTs
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.
Should expr be the original expression that the placeholder will be replaced with?
Strictly speaking, the value that we are supposed to pass to the BoundCall
constructor for initialBindingReceiverIsSubjectToCloning
parameter should reflect what is actually going to happen during code generation. I assume that during lowering, a key value pair will be captured in a temp and then the accessor will be invoked on that temp. Therefore, a cloning will happen, but not as part of IL emit for the node itself.
On the other hand, as far as I understand, the actual initialBindingReceiverIsSubjectToCloning
value is interesting for ref safety analysis only. Does this node go through the analysis? If it doesn't, then passing ThreeState.Unknown
would be the honest and the simplest thing to do. If it does, again, strictly speaking, we should pass ThreeState.True
. However, it looks like GetInvocationArgumentsForEscape
doesn't like placeholders as receivers and it assumes specific SafeContext value for the future temp, which might or might not reflect the actual SafeContext of the temp introduced during lowering. At the same time, we probably can assume that the KeyValuePair
is not a ref struct and the accessor takes no refs and returns no refs, there should be no ref safety issues due to the cloning (a ref to that temp location cannot escape from the accessor), therefore, passing ThreeState.False
would be correct (little explanation comment might be helpful for a future code reader).
In my opinion, calling ReceiverIsSubjectToCloning
here with placeholder probably doesn't help anyone, and as a follow-up we probably should change it to either assert on placeholders, or return ThreeState.Unknown
when type is not known to be a reference type.
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 detailed explanation. I've switched back to ThreeState.False
and added a comment from your explanation.
@@ -1473,8 +1475,6 @@ class Program | |||
} | |||
"""; | |||
comp = CreateCompilation([sourceA, sourceB2], targetFramework: TargetFramework.Net80); | |||
// PROTOTYPE: Update the params-collection spec so it's clear that we require "... a factory method callable with no additional |
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.
@@ -16309,7 +16309,6 @@ static void Main() | |||
} | |||
"""; | |||
comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); | |||
// PROTOTYPE: ERR_CollectionBuilderAttributeMethodNotFound error message is stale. It should say "... with a first parameter of type 'ReadOnlySpan<object> callable with no additional arguments, ...". |
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.
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.
LGTM Thanks (iteration 5)
@@ -6631,8 +6631,6 @@ static BoundCall bindKeyOrValue(SyntaxNode syntax, BoundExpression expr, MethodS | |||
return new BoundCall( | |||
syntax, | |||
receiverOpt: expr, | |||
// PROTOTYPE: What is the correct value for receiver cloning? Test with expression element |
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.
Were the indicated tests added? It wasn't clear to me why these accessors being on well-known type affects what value we should pass here.
It seems like existing places in the binder where False
is passed here, are taking care to ensure that the receiver is something we can take a reference to.
@@ -907,8 +904,6 @@ private BoundCollectionExpression ConvertCollectionExpression( | |||
{ | |||
var analyzedArguments = AnalyzedArguments.GetInstance(); | |||
withElement.AddToArguments(analyzedArguments); | |||
// PROTOTYPE: If there are multiple with() elements, should with() elements after |
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.
As long as the bad constructor calls say they have errors in the operation tree, this seems fine. That's just us giving the full information about what we think the code means.
SyntaxKind.SpreadElement, | ||
SyntaxKind.KeyValuePairElement, | ||
SyntaxKind.WithElement, | ||
SyntaxKind.WithElement, // Needed when language version is updated. |
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 didn't understand what this means. Is the with-element in TestResource.resx not detected at the moment? #Resolved
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 parser only generates SyntaxKind.WithElement
when compiling with LanguageVersion.Preview
, but this test currently uses LanguageVersion.Latest
. When Latest
is updated, this case can be removed.
string sourceB = """ | ||
class Program | ||
{ | ||
static MyDictionary<K, V> FromPair1<K, V>(K k, V v) |
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.
Some tests maybe worth adding after feature merge:
MyDictionary<K, V> d = [k:v]; return d;
FromPair(ref K k, ref V v) => [k:v]
MyDictionary<K, V> d = [MakeKey():v]; return d;
#Resolved
// PROTOTYPE: [with(x)] and [with(x), y] should result in errors since x should not be included in the params argument. | ||
// https://github.com/dotnet/roslyn/issues/77866: [with(x)] and [with(x), y] should | ||
// result in errors since x should not be included in the params argument. Should | ||
// be fixed when the last parameter of the builder method is the items parameter. |
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.
Is this saying we're going to add some enforcement later which will avoid including the 'with' arguments for the last parameter of Create? It might be good to demonstrate what arguments are actually being passed for items
in Create(items)
, e.g. with expectedOutput
. But if it's thought to be too much of a corner case, we can just wait to take the fix instead. #Resolved
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.
Yes, I expect the change for parameter order will include some enforcement to catch cases where with
arguments may be used for the last parameter.
@@ -6666,6 +6664,10 @@ private BoundExpression BindDictionaryItemAssignment( | |||
return new BoundCall( | |||
syntax, | |||
receiverOpt: implicitReceiver, | |||
// initialBindingReceiverIsSubjectToCloning is used for ref safety analysis, KeyValuePair<,> is |
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.
9705bdf
into
dotnet:features/dictionary-expressions
No description provided.