Skip to content

Conversation

@AlekseyTs
Copy link
Contributor

No description provided.

@AlekseyTs AlekseyTs requested review from 333fred and cston April 18, 2025 14:16
@AlekseyTs AlekseyTs requested a review from a team as a code owner April 18, 2025 14:16
@ghost ghost added the untriaged Issues and PRs which have not yet been triaged by a lead label Apr 18, 2025
@AlekseyTs AlekseyTs requested a review from RikkiGibson April 18, 2025 17:48
@jaredpar jaredpar removed the untriaged Issues and PRs which have not yet been triaged by a lead label Apr 19, 2025
// return X(c += c1);
Diagnostic(ErrorCode.ERR_EscapeVariable, "c").WithArguments("scoped C c").WithLocation(7, 18)
);
}
Copy link
Contributor

@cston cston Apr 21, 2025

Choose a reason for hiding this comment

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

}

Are we testing by-ref parameters? Consider testing the following, with/without [UnscopedRef]:

using System.Diagnostics.CodeAnalysis;
ref struct C
{
    private ref readonly int _i;
    public void operator +=([UnscopedRef] in int right) { _i = ref right; }
    public C M1(C c)
    {
        return c += 1;
    }
}
``` #Resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added CompoundAssignment_00752_Consumption_RefSafety and CompoundAssignment_00753_Consumption_RefSafety


public ref struct C
{
[UnscopedRef]
Copy link
Contributor

@cston cston Apr 21, 2025

Choose a reason for hiding this comment

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

[UnscopedRef]

Does this attribute have any effect on the test? #Resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Does this attribute have any effect on the test?

I don't think the attribute affects the behavior, it still feels useful to observe.

// return c += c1;
Diagnostic(ErrorCode.ERR_EscapeVariable, "c1").WithArguments("scoped C c1").WithLocation(6, 21)
);
}
Copy link
Contributor

@cston cston Apr 21, 2025

Choose a reason for hiding this comment

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

}

Consider testing with public void operator +=(scoped C right) { } as well. #Resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added as CompoundAssignment_00749_Consumption_RefSafety

// return Y(c = X(c, c1));
Diagnostic(ErrorCode.ERR_EscapeVariable, "c = X(c, c1)").WithArguments("scoped C c").WithLocation(12, 18)
);
}
Copy link
Contributor

@cston cston Apr 21, 2025

Choose a reason for hiding this comment

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

}

Consider testing with static C operator +(C left, scoped C right) => left; as well. #Resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added UserDefinedBinaryOperator_RefStruct_Compound_ScopedTarget_03

@RikkiGibson RikkiGibson self-assigned this Apr 21, 2025
Copy link
Member

@RikkiGibson RikkiGibson left a comment

Choose a reason for hiding this comment

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

LGTM except for one question.

resultKind: LookupResultKind.Viable,
originalUserDefinedOperatorsOpt: ImmutableArray<MethodSymbol>.Empty,
leftType);
getResultType(node, leftType, diagnostics));
Copy link
Member

@RikkiGibson RikkiGibson Apr 21, 2025

Choose a reason for hiding this comment

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

Could you please explain why we are doing this? I thought that ordinarily, the type of an expression doesn't depend on whether the expression is used. #Resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I thought that ordinarily, the type of an expression doesn't depend on whether the expression is used.

Yes, usually this is the case. However, some forms of ++/-- are not supported when result is used. In addition, lowering of ++/--/ and compound assignments is different (produces much simpler result, and results in much simpler IL) when we know that result is not used. In such cases lowering produce a node with void type (the operator method invocation) and we generally don't like changing types of expressions during lowering. We even have an assert about that in LocalRewriter.VisitExpressionImpl. Basically this change cleans up and aligns implementation for compound operators with implementation for ++/--. The change is also somewhat related to ref safety analysis because it is often performed based on the type of expression.

BTW, there is another example of changing type of expression to void based on whether it is used - conditional access.

@AlekseyTs AlekseyTs requested a review from cston April 21, 2025 22:26
var source = """
public ref struct C
{
public static C operator +(C left, scoped C right) => left;
Copy link
Contributor

@cston cston Apr 21, 2025

Choose a reason for hiding this comment

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

public static C operator +(C left, scoped C right) => left;

Sorry, I guess this should be static C operator +(scoped C left, C right) => right; to test a different case than the previous test. #Resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added UserDefinedBinaryOperator_RefStruct_Compound_ScopedTarget_04

@AlekseyTs AlekseyTs requested a review from RikkiGibson April 21, 2025 23:04
@AlekseyTs AlekseyTs merged commit 96a2dcd into dotnet:features/UserDefinedCompoundAssignment Apr 22, 2025
24 checks passed
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.

4 participants