Marcel Taeumel uploaded a new version of Kernel to project The Treated Inbox: http://source.squeak.org/treated/Kernel-jar.1480.mcz
==================== Summary ====================
Name: Kernel-jar.1480 Author: jar Time: 9 June 2022, 7:53:32.496688 pm UUID: 1504c554-482d-a94e-b292-ab2c46c6d865 Ancestors: Kernel-mt.1479
Fix a bug: when debugging things like this:
[^2] ensure: [Transcript cr; show: 'done']
if we step into the protected block [^2] and then step over ^2, we incorrectly get a BlockCannotReturn error.
Improved comment; please remove Kernel-jar.1415 from the Inbox.
This is an alternative to my older version in Kernel-jar.1421; the solution remains the same but it attempts to present a cleaner code (addressing Christoph's objection in [2] and [3]) and improves the comment.
The bug is described in detail in Kernel-nice.1407 and discussed in [1] and most recently in [2] and [3]: [1] http://forum.world.st/stepping-over-non-local-return-in-a-protected-block-td... [2] http://lists.squeakfoundation.org/pipermail/squeak-dev/2021-August/216214.ht... [3] http://lists.squeakfoundation.org/pipermail/squeak-dev/2021-November/216971....
=============== Diff against Kernel-mt.1479 ===============
Item was changed: ----- Method: Context>>resume:through: (in category 'controlling') ----- resume: value through: firstUnwindCtxt "Unwind thisContext to self and resume with value as result of last send. Execute any unwind blocks while unwinding. ASSUMES self is a sender of thisContext."
| ctxt unwindBlock | self isDead ifTrue: [self cannotReturn: value to: self]. + ctxt := firstUnwindCtxt value. "evaluate in case firstUnwindCtxt is a block (see comment in #return:from:)" - ctxt := firstUnwindCtxt. [ctxt isNil] whileFalse: [(ctxt tempAt: 2) ifNil: [ctxt tempAt: 2 put: true. unwindBlock := ctxt tempAt: 1. thisContext terminateTo: ctxt. unwindBlock value]. ctxt := ctxt findNextUnwindContextUpTo: self]. thisContext terminateTo: self. ^value !
Item was changed: ----- Method: Context>>return:from: (in category 'instruction decoding') ----- return: value from: aSender "For simulation. Roll back self to aSender and return value from it. Execute any unwind blocks on the way. ASSUMES aSender is a sender of self"
+ "Note: when debugging things like this: + [^2] ensure: [Transcript cr; show: 'done'] + if we step into the protected block [^2] and then step over ^2, we incorrectly get a BlockCannotReturn. + The root cause of this is that during simulation #runUntilErrorOrReturnFrom: inserts a new unwind + context between the top of the stack and 'newTop' so we can't supply the next unwind context to + #aboutToReturn:through: now but must postpone the search for the next unwind context until the + right moment, i.e. until #resume:through: gets executed using the supplied next unwind context. + One solution is to send a block + [thisContext findNextUnwindContextUpTo: newTop] + that will execute the search in #resume:through: instead of sending the next unwind context. + Indeed we must modify #resume:through: to evaluate its second argument in case it's this block. + + The objection against such a solution is we are creating a dependency between these two methods. + See more in http://lists.squeakfoundation.org/pipermail/squeak-dev/2021-August/216214.ht..." + | newTop | aSender isDead ifTrue: [^self send: #cannotReturn: to: self with: {value}]. newTop := aSender sender. (self findNextUnwindContextUpTo: newTop) ifNotNil: + [^self send: #aboutToReturn:through: to: self with: {value. [thisContext findNextUnwindContextUpTo: newTop]}]. - [:unwindProtectCtxt| - ^self send: #aboutToReturn:through: to: self with: {value. unwindProtectCtxt}]. self releaseTo: newTop. newTop ifNotNil: [newTop push: value]. ^newTop!
packages@lists.squeakfoundation.org