dotnet / dotnet/csharpstandard
Assignment rules for properties/events/fields should account for generic receivers
- Dominant language
- C#
- Stars
- 815
- Forks
- 99
- Avg merge
- 1d 14h
- Merged PRs (30d)
- 16
Description
The spec says: "When a property or indexer declared in a struct_type is the target of an assignment, the instance expression associated with the property or indexer access shall be classified as a variable. If the instance expression is classified as a value, a binding-time error occurs." (in the [Simple Assignment](https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/expressions.md#12212-simple-assignment) section).
But that rule should be tweaked in two ways:
1. we should be checking the operand of the property, instead of the declaring type of the property
2. we should check that the operand is not a reference type, rather than checking that it is a struct-type
Checking the operand is motivated by this example:
```
struct S
{
public object P { get; set; }
}
interface I
{
object P { get; set; }
}
class C
{
static void M()
where T : struct, I
{
default(S).P = null; // error
default(T).P = null; // should error here too
}
}
```
Checking for "not a reference type" is motivated by this example:
```
struct S
{
public object P { get; set; }
}
interface I
{
object P { get; set; }
}
class C
{
static void M()
where T : I
{
default(T).P = null; // should likely error here too (since T may be substituted with a struct)
}
}
```
Note: the roslyn compiler has implemented the first change (checking the operand) but not the second one yet.
```
///
/// SPEC: When a property or indexer declared in a struct-type is the target of an
/// SPEC: assignment, the instance expression associated with the property or indexer
/// SPEC: access must be classified as a variable. If the instance expression is
/// SPEC: classified as a value, a compile-time error occurs. Because of 7.6.4,
/// SPEC: the same rule also applies to fields.
///
///
/// NOTE: The spec fails to impose the restriction that the event receiver must be classified
/// as a variable (unlike for properties - 7.17.1). This seems like a bug, but we have
/// production code that won't build with the restriction in place (see DevDiv #15674).
///
private static bool RequiresVariableReceiver(BoundExpression receiver, Symbol symbol)
{
return symbol.RequiresInstanceReceiver()
&& symbol.Kind != SymbolKind.Event
&& receiver?.Type?.IsValueType == true;
}
```
Contributor guide
Assessment
This issue has not been assessed yet.