dotnet / dotnet/csharpstandard

Assignment rules for properties/events/fields should account for generic receivers

Open
#1,078 0 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.