@@ -226,11 +226,27 @@ BoundExpression rewriteAssignment(BoundExpression leftRead, BoundExpression righ
226
226
}
227
227
228
228
Debug . Assert ( TypeSymbol . Equals ( transformedLHS . Type , node . Left . Type , TypeCompareKind . AllIgnoreOptions ) ) ;
229
+
230
+ if ( IsNewExtensionMemberAccessWithByValPossiblyStructReceiver ( transformedLHS ) )
231
+ {
232
+ // We need to create a tree that ensures that receiver of 'set' is evaluated after the binary operation
233
+ BoundLocal binaryResult = _factory . StoreToTemp ( opFinal , out BoundAssignmentOperator assignmentToTemp , refKind : RefKind . None ) ;
234
+ BoundExpression assignment = MakeAssignmentOperator ( syntax , transformedLHS , binaryResult , used : used , isChecked : isChecked , isCompoundAssignment : true ) ;
235
+ Debug . Assert ( assignment . Type is { } ) ;
236
+ return new BoundSequence ( syntax , [ binaryResult . LocalSymbol ] , [ assignmentToTemp ] , assignment , assignment . Type ) ;
237
+ }
238
+
229
239
return MakeAssignmentOperator ( syntax , transformedLHS , opFinal , used : used , isChecked : isChecked , isCompoundAssignment : true ) ;
230
240
}
231
241
}
232
242
233
- private BoundExpression ? TransformPropertyOrEventReceiver ( Symbol propertyOrEvent , BoundExpression ? receiverOpt , bool isRegularCompoundAssignment , ArrayBuilder < BoundExpression > stores , ArrayBuilder < LocalSymbol > temps )
243
+ private static bool IsNewExtensionMemberAccessWithByValPossiblyStructReceiver ( BoundExpression transformedLHS )
244
+ {
245
+ return transformedLHS is BoundPropertyAccess { PropertySymbol : { } property } && property . GetIsNewExtensionMember ( ) &&
246
+ property . ContainingType . ExtensionParameter is { RefKind : RefKind . None , Type . IsReferenceType : false } ;
247
+ }
248
+
249
+ private BoundExpression ? TransformPropertyOrEventReceiver ( Symbol propertyOrEvent , BoundExpression ? receiverOpt , ArrayBuilder < BoundExpression > stores , ArrayBuilder < LocalSymbol > temps )
234
250
{
235
251
Debug . Assert ( propertyOrEvent . Kind == SymbolKind . Property || propertyOrEvent . Kind == SymbolKind . Event ) ;
236
252
@@ -272,7 +288,9 @@ BoundExpression rewriteAssignment(BoundExpression leftRead, BoundExpression righ
272
288
// SPEC VIOLATION: However, for compatibility with Dev12 we will continue treating all generic type parameters, constrained or not,
273
289
// SPEC VIOLATION: as value types.
274
290
Debug . Assert ( rewrittenReceiver . Type is { } ) ;
275
- var variableRepresentsLocation = rewrittenReceiver . Type . IsValueType || rewrittenReceiver . Type . Kind == SymbolKind . TypeParameter ;
291
+ var variableRepresentsLocation = propertyOrEvent . GetIsNewExtensionMember ( ) ?
292
+ ! rewrittenReceiver . Type . IsReferenceType :
293
+ ( rewrittenReceiver . Type . IsValueType || rewrittenReceiver . Type . Kind == SymbolKind . TypeParameter ) ;
276
294
277
295
var receiverTemp = _factory . StoreToTemp (
278
296
rewrittenReceiver ,
@@ -286,9 +304,10 @@ BoundExpression rewriteAssignment(BoundExpression leftRead, BoundExpression righ
286
304
stackLocalsOpt : null ) ) ;
287
305
temps . Add ( receiverTemp . LocalSymbol ) ;
288
306
289
- if ( ! isRegularCompoundAssignment &&
290
- receiverTemp . LocalSymbol . IsRef &&
291
- CodeGenerator . IsPossibleReferenceTypeReceiverOfConstrainedCall ( receiverTemp ) &&
307
+ if ( receiverTemp . LocalSymbol . IsRef &&
308
+ ( propertyOrEvent . GetIsNewExtensionMember ( ) ?
309
+ ! receiverTemp . Type . IsValueType :
310
+ CodeGenerator . IsPossibleReferenceTypeReceiverOfConstrainedCall ( receiverTemp ) ) &&
292
311
! CodeGenerator . ReceiverIsKnownToReferToTempIfReferenceType ( receiverTemp ) )
293
312
{
294
313
BoundAssignmentOperator ? extraRefInitialization ;
@@ -678,7 +697,7 @@ private BoundExpression TransformCompoundAssignmentLHS(BoundExpression originalL
678
697
{
679
698
// This is a temporary object that will be rewritten away before the lowering completes.
680
699
return propertyAccess . Update ( TransformPropertyOrEventReceiver ( propertyAccess . PropertySymbol , propertyAccess . ReceiverOpt ,
681
- isRegularCompoundAssignment , stores , temps ) ,
700
+ stores , temps ) ,
682
701
propertyAccess . InitialBindingReceiverIsSubjectToCloning , propertyAccess . PropertySymbol , propertyAccess . AutoPropertyAccessorKind , propertyAccess . ResultKind , propertyAccess . Type ) ;
683
702
}
684
703
}
@@ -804,10 +823,9 @@ private BoundExpression TransformCompoundAssignmentLHS(BoundExpression originalL
804
823
805
824
if ( eventAccess . EventSymbol . IsWindowsRuntimeEvent )
806
825
{
807
- Debug . Assert ( ! isRegularCompoundAssignment ) ;
808
826
// This is a temporary object that will be rewritten away before the lowering completes.
809
827
return eventAccess . Update ( TransformPropertyOrEventReceiver ( eventAccess . EventSymbol , eventAccess . ReceiverOpt ,
810
- isRegularCompoundAssignment , stores , temps ) ,
828
+ stores , temps ) ,
811
829
eventAccess . EventSymbol , eventAccess . IsUsableAsField , eventAccess . ResultKind , eventAccess . Type ) ;
812
830
}
813
831
0 commit comments