Skip to content

Commit b02cec8

Browse files
authored
Fix code gen for some increment/compound assignment scenarios involving constrained calls. (#79293)
Fixes #79268
1 parent 604c176 commit b02cec8

File tree

6 files changed

+2428
-307
lines changed

6 files changed

+2428
-307
lines changed

src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CompoundAssignmentOperator.cs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,16 @@ BoundExpression rewriteAssignment(BoundExpression leftRead, BoundExpression righ
274274
Debug.Assert(rewrittenReceiver.Type is { });
275275
var variableRepresentsLocation = rewrittenReceiver.Type.IsValueType || rewrittenReceiver.Type.Kind == SymbolKind.TypeParameter;
276276

277-
var receiverTemp = _factory.StoreToTemp(rewrittenReceiver, out assignmentToTemp, refKind: variableRepresentsLocation ? RefKind.Ref : RefKind.None);
277+
var receiverTemp = _factory.StoreToTemp(
278+
rewrittenReceiver,
279+
out assignmentToTemp,
280+
refKind: variableRepresentsLocation ? RefKind.Ref : RefKind.None,
281+
isKnownToReferToTempIfReferenceType: !variableRepresentsLocation || rewrittenReceiver.Type.IsValueType ||
282+
!CodeGenerator.HasHome(rewrittenReceiver,
283+
CodeGenerator.AddressKind.Constrained,
284+
_factory.CurrentFunction,
285+
peVerifyCompatEnabled: false,
286+
stackLocalsOpt: null));
278287
temps.Add(receiverTemp.LocalSymbol);
279288

280289
if (!isRegularCompoundAssignment &&
@@ -476,7 +485,6 @@ private BoundIndexerAccess TransformIndexerAccessContinued(
476485

477486
private BoundExpression TransformImplicitIndexerAccess(
478487
BoundImplicitIndexerAccess indexerAccess,
479-
bool isRegularCompoundAssignment,
480488
ArrayBuilder<BoundExpression> stores,
481489
ArrayBuilder<LocalSymbol> temps,
482490
bool isDynamicAssignment)
@@ -486,19 +494,19 @@ private BoundExpression TransformImplicitIndexerAccess(
486494
_compilation.GetWellKnownType(WellKnownType.System_Index),
487495
TypeCompareKind.ConsiderEverything))
488496
{
489-
return TransformIndexPatternIndexerAccess(indexerAccess, isRegularCompoundAssignment, stores, temps, isDynamicAssignment);
497+
return TransformIndexPatternIndexerAccess(indexerAccess, stores, temps, isDynamicAssignment);
490498
}
491499

492500
throw ExceptionUtilities.UnexpectedValue(indexerAccess.Argument.Type);
493501
}
494502

495-
private BoundExpression TransformIndexPatternIndexerAccess(BoundImplicitIndexerAccess implicitIndexerAccess, bool isRegularCompoundAssignment, ArrayBuilder<BoundExpression> stores, ArrayBuilder<LocalSymbol> temps, bool isDynamicAssignment)
503+
private BoundExpression TransformIndexPatternIndexerAccess(BoundImplicitIndexerAccess implicitIndexerAccess, ArrayBuilder<BoundExpression> stores, ArrayBuilder<LocalSymbol> temps, bool isDynamicAssignment)
496504
{
497505
Debug.Assert(implicitIndexerAccess.IndexerOrSliceAccess.GetRefKind() == RefKind.None);
498506
var access = GetUnderlyingIndexerOrSliceAccess(
499507
implicitIndexerAccess,
500508
isLeftOfAssignment: true,
501-
isRegularAssignmentOrRegularCompoundAssignment: isRegularCompoundAssignment,
509+
isRegularAssignment: false,
502510
cacheAllArgumentsOnly: false,
503511
stores, temps);
504512

@@ -696,7 +704,7 @@ private BoundExpression TransformCompoundAssignmentLHS(BoundExpression originalL
696704

697705
if (implicitIndexerAccess.GetRefKind() == RefKind.None)
698706
{
699-
return TransformImplicitIndexerAccess(implicitIndexerAccess, isRegularCompoundAssignment, stores, temps, isDynamicAssignment);
707+
return TransformImplicitIndexerAccess(implicitIndexerAccess, stores, temps, isDynamicAssignment);
700708
}
701709
}
702710
break;
@@ -796,6 +804,7 @@ private BoundExpression TransformCompoundAssignmentLHS(BoundExpression originalL
796804

797805
if (eventAccess.EventSymbol.IsWindowsRuntimeEvent)
798806
{
807+
Debug.Assert(!isRegularCompoundAssignment);
799808
// This is a temporary object that will be rewritten away before the lowering completes.
800809
return eventAccess.Update(TransformPropertyOrEventReceiver(eventAccess.EventSymbol, eventAccess.ReceiverOpt,
801810
isRegularCompoundAssignment, stores, temps),

src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_IndexerAccess.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ private BoundExpression VisitIndexPatternIndexerAccess(BoundImplicitIndexerAcces
458458

459459
BoundExpression rewrittenIndexerAccess = GetUnderlyingIndexerOrSliceAccess(
460460
node, isLeftOfAssignment,
461-
isRegularAssignmentOrRegularCompoundAssignment: isLeftOfAssignment,
461+
isRegularAssignment: isLeftOfAssignment,
462462
cacheAllArgumentsOnly: false,
463463
sideeffects, locals);
464464

@@ -471,7 +471,7 @@ private BoundExpression VisitIndexPatternIndexerAccess(BoundImplicitIndexerAcces
471471
private BoundExpression GetUnderlyingIndexerOrSliceAccess(
472472
BoundImplicitIndexerAccess node,
473473
bool isLeftOfAssignment,
474-
bool isRegularAssignmentOrRegularCompoundAssignment,
474+
bool isRegularAssignment,
475475
bool cacheAllArgumentsOnly,
476476
ArrayBuilder<BoundExpression> sideeffects,
477477
ArrayBuilder<LocalSymbol> locals)
@@ -508,7 +508,7 @@ private BoundExpression GetUnderlyingIndexerOrSliceAccess(
508508
if (receiverLocal.LocalSymbol.IsRef &&
509509
CodeGenerator.IsPossibleReferenceTypeReceiverOfConstrainedCall(receiverLocal) &&
510510
!CodeGenerator.ReceiverIsKnownToReferToTempIfReferenceType(receiverLocal) &&
511-
((isLeftOfAssignment && !isRegularAssignmentOrRegularCompoundAssignment) ||
511+
((isLeftOfAssignment && !isRegularAssignment) ||
512512
!CodeGenerator.IsSafeToDereferenceReceiverRefAfterEvaluatingArguments(ImmutableArray.Create(makeOffsetInput))))
513513
{
514514
BoundAssignmentOperator? extraRefInitialization;

src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_ObjectOrCollectionInitializerExpression.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,7 @@ private void AddObjectInitializer(
519519
rewrittenAccess = GetUnderlyingIndexerOrSliceAccess(
520520
implicitIndexer,
521521
isLeftOfAssignment: !isRhsNestedInitializer,
522-
isRegularAssignmentOrRegularCompoundAssignment: true,
522+
isRegularAssignment: true,
523523
cacheAllArgumentsOnly: true,
524524
result, temps);
525525

src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_UnaryOperator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -582,7 +582,7 @@ public BoundExpression VisitBuiltInOrStaticIncrementOperator(BoundIncrementOpera
582582

583583
// This will be filled in with the LHS that uses temporaries to prevent
584584
// double-evaluation of side effects.
585-
BoundExpression transformedLHS = TransformCompoundAssignmentLHS(node.Operand, isRegularCompoundAssignment: true, tempInitializers, tempSymbols, isDynamic);
585+
BoundExpression transformedLHS = TransformCompoundAssignmentLHS(node.Operand, isRegularCompoundAssignment: false, tempInitializers, tempSymbols, isDynamic);
586586
TypeSymbol? operandType = transformedLHS.Type; //type of the variable being incremented
587587
Debug.Assert(operandType is { });
588588
Debug.Assert(TypeSymbol.Equals(operandType, node.Type, TypeCompareKind.ConsiderEverything2));

0 commit comments

Comments
 (0)