Skip to content

12.6.6 function member invocation lacks specification of timing of reading receiver #1584

@GeeLaw

Description

@GeeLaw

Describe the bug In 12.6.6 function member invocation, for E.M(args...), if E is not value type or does not implement M, then:

  1. evaluate E
  2. evaluate args...
  3. if E is value type, box it and treat it as the boxed instance
  4. invoke M

Suppose E is classified as a variable, then it's unclear when the value of E is read. Is it right after 1, or right before 3? The two options are not equivalent, because evaluation of args... could modify the value stored in that variable.

After some testing, it turns out that

  • when E is reference type, the value (reference) is read right after 1,
    • Suppose E is the identifier of a local variable and args... reassigns this variable, the receiver of E.M(args...) is the (old) object before reassignment.
  • but, when E is value type, the value is read right before 3.
    • Suppose E is the identifier of a local variable and args... reassigns this variable, the receiver of E.M(args...) is a boxed instance of the reassigned (new) value.

The timings are different!

Example

See replies to this issue.

Expected behavior

The standard should clearly specify the timing of reading of value from variable.

Additional context

Found when investigating the semantics of constrained. callvirt.. See dotnet/dotnet-api-docs#12359.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions