Skip to content

Weird behavior in accessors after deleting an instvar #122

Closed
@MariusDoe

Description

@MariusDoe

I have noticed a weird behavior that occurs when you delete an instvar from a class, but keep the accessors for it and call them.

Steps to reproduce

  1. Create a class Dummy
  2. Add an instvar myVar
  3. Add accessors myVar and myVar (^ myVar and myVar := anObject, respectively)
  4. Delete the instvar myVar
  5. Open a workspace
  6. Execute Dummy new myVar: 42.
  7. Print Dummy new myVar (note: this is a new instance, do not keep the instance from the previous step)

Expected behavior

One of the following:

  • An error is shown in step 4 (something like The instVar myVar is still referenced in these 2 methods: ...)
  • An error is shown in step 6 (something like The instVar myVar does not exist)
  • nil is printed in step 7

Actual behavior

42 is printed in step 7

Analysis

The problem occurs because after step 4, the accessors use the bytecodes pushLitVar: and popIntoLit:, with the referenced literal being the global Undeclared associationAt: #myVar. This results in the myVar: call storing the 42 into the Association's value, which the myVar call on an unrelated instance will read, because the method references the same (global) Association in its literals.

I have traced the reason for the use of these bytecodes:

  1. Class>>compileAllFrom: is called during step 4
  2. During parsing, Parser>>variable is called
  3. It doesn't find the variable myVar in scope
  4. It calls Parser>>correctVariable:interval:
  5. Because the recompilation of all methods is not interactive, Encoder>>undeclared: is called
  6. Encoder>>global:name: is called with Undeclared associationAt: #myVar
  7. A LiteralVariableNode with the association as its key is returned
  8. Afterwards, either an AssignmentNode (for the setter) or a ReturnNode (for the getter) is created
  9. After parsing, MethodNode>>generate: is called
  10. In the setter case, AssignmentNode>>emitCodeForEffect:encoder: calls LiteralVariableNode>>emitCodeForStorePop:encoder:, which calls Encoder>>genStorePopLiteralVar:
  11. In the getter case, ReturnNode>>emitCodeForValue:encoder: (indirectly) calls LiteralVariableNode>>emitCodeForValue:encoder:, which calls Encoder>>genPushLiteralVar:
  12. Both reference the global Association, which was previously written into the literals of the Encoder

Metadata

Metadata

Assignees

No one assigned

    Labels

    base system[SCOPE] Squeak's basic (language) concerns such as Kernel, Collections, Graphics, Networkignored[RATING] No longer valid or necessary.programmer[SCOPE] It is for the (maybe professional) programmer

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions