[ok [ summary: {Unwind functions don't propagate when called in function arg expression that accepts error! values} description: {The structured escape functions are BREAK, CONTINUE, THROW, EXIT and RETURN; the terms "unwinds" and "unwind functions" are used herein for brevity. Unwind functions do their work by returning a special error! value - not the same type that you can create with MAKE error!. When one of these values is returned from a function, execution of the code that called the function is stopped and the value is returned again, propagating up the call stack, unwinding the stack and cleaning up as it goes, until they are caught by special handlers (loops, CATCH, function calls, the console). See http://www.rebol.com/r3/notes/errors.html for details. However, there is a quirk: When an unwind value is returned from a function, if that function call expression would return to the argument list of a function that accepts error! or any-type! arguments, then the unwind stops propagating and is passed as an argument value. This quirk is arguably a *major* bug because of how many functions we have that accept error! arguments, such as TYPE?, ERROR?, all of the type checking functions, and ironically THROW and RETURN themselves. This bug doesn't affect the throwing of regular errors when they've been triggered, nor does it affect the treatment of errors that haven't been triggered yet or were already caught by TRY or ATTEMPT. It's only the unwind pseudo-errors, and only when the expressions that generate them are passed as function arguments to functions that accept error! values. The theoretical fix for this bug would be to fix function argument evaluation in DO and APPLY so that when unwinds are encountered they are propagated safely, even if the function argument accepts error!. Only untriggered normal error! values should be passed as an argument to the function, not unwinds. This shouldn't affect the top-level error handler because unwinds aren't thrown like regular errors, they are return values. See also #771 and #862, which illustrate specific cases of the larger problem. #851 might be related.} code: {>> error? break == true ; The unwind is passed to the ERROR? function instead of propagated. ; Should be ** Throw error: no loop to break >> loop 1 [error? break/return "good" "buggy"] == "buggy" ; Should be "good" ; This is good (though see #1506) >> attempt [break] ** Throw error: no loop to break ; This is bad, should trigger the same error >> type? attempt [break] == error! ; Common code patterns >> loop 1 [break print "This should not be printed!"] >> loop 1 [try [break] print "This should not be printed!"] >> loop 1 [error? try [break] print "This should not be printed!"] This should not be printed! >> loop 1 [attempt [break] print "This should not be printed!"] >> loop 1 [type? attempt [break] print "This should not be printed!"] This should not be printed!} version: "alpha 97" severity: "major" status: "built" resolution: "open" priority: "high" type: "Bug" platform: "All" created: 3-Mar-2010/22:20:31 modified: 19-Feb-2014/20:01:20 user: "BrianH" category: "Error Handling" reproduce: "Always" fixed-in: "r3 master" project: "REBOL 3.0" comments: [[2070 "BrianH" 7-Mar-2010/21:57:17 {Fixed the phrasing to match the description of error processing and unwind handling described here: http://www.rebol.com/r3/notes/errors.html}] [2073 "Ladislav" 8-Mar-2010/15:39:39 {I think, that the bugs #771 and #1509 are caused by mixing the "internal" and "external" datatypes - an "internal unwind" (also "triggered unwind"/"caused unwind"/"activated unwind" - an unwind *already used* to unwind the execution back to a marker) should not be the same as an "external unwind" (also "untriggered unwind"/"inactive unwind" - a value, which is/can be manipulated by the interpreter as a "Rebol value")}] [2080 "Ladislav" 9-Mar-2010/10:51:38 {Regarding:^M ^M ; This is good^M >> attempt [break]^M ** Throw error: no loop to break^M ^M As far as #1506 is concerned, the above behaviour is not good.}] [2082 "BrianH" 9-Mar-2010/12:34:52 {No, that behavior is good. The ATTEMPT is called before the BREAK, not afterwards, so it is passed the code block containing the BREAK as an argument, not the result of the BREAK. It's the result of the BREAK that is the problem, not the code block containing the original expression.^M ^M For an example of really nasty code, see #1515: Apparently the set-word assignment of errors also lets you assign unwinds, and when you DO the saved value it is like executing the unwind function again. This lets you break a sandbox in the way that #1004 was supposed to fix. This is really bad.}] [2087 "Sunanda" 11-Mar-2010/10:23:16 {I posted this in the REBOL3 Blog. Ladislav has suggested I also ensure it is in the CureCode records:^M ^M To document two issues that may be related to this:^M ^M First:^M ^M do "while [] []"^M ^M is bad when executed in the console, but good when executed in a script:^M ^M attempt [do "while [] []"]^M ^M Second: R2 and R3 respond differently here (I am aware of Curecode #666):^M ^M while [return 55][print 1]^M ^M Some discussion of these examples here:^M ^M http://www.rebol.org/aga-display-posts.r?post=r3wp771x1494}] [2090 "Ladislav" 12-Mar-2010/10:32:16 {Sorry, Brian, you are right, that as far as #1509 is concerned, the behaviour may be considered OK, but, as far as #1506 is concerned, it is a bug.}] [2092 "BrianH" 12-Mar-2010/18:37 {Sunanda, the first of those is because of #851, and the second is related to #1509 but not quite the same thing; see #1519 for details.^M ^M Tweaked the wording to reflect new information, and to mention #1506.}] [2112 "BrianH" 23-Mar-2010/17:41:08 {New crash bug that is a side effect of this: #1535.}] [2757 "Ladislav" 2-Nov-2010/12:19:13 "in the core-tests suite"] [2839 "abolka" 11-Nov-2010/23:50:01 {QUIT and HALT are "throws" not "unwindws" and unaffected by this.}] [2842 "BrianH" 12-Nov-2010/7:42:16 {Thanks, Andreas. I had noticed that earlier this week (much to my surprise, for some reason), but had not fixed the description in this ticket. It's fixed now.}]] history: [ [19-Feb-2014/20:01:20 "BrianH" "Status " "Modified" "submitted => built"] [19-Feb-2014/20:01:20 "BrianH" "Fixedin " "Modified" "=> r3 master"] [12-Nov-2010/7:42:16 "BrianH" "Comment : 0002842" "Added" "-"] [12-Nov-2010/7:40:25 "BrianH" "Description " "Modified" "-"] [11-Nov-2010/23:50:01 "abolka" "Comment : 0002839" "Added" "-"] [2-Nov-2010/12:19:13 "Ladislav" "Comment : 0002757" "Added" "-"] [2-Nov-2010/0:39:20 "BrianH" "Code " "Modified" "-"] [23-Mar-2010/17:41:08 "BrianH" "Comment : 0002112" "Added" "-"] [12-Mar-2010/22:37:46 "BrianH" "Comment : 0002092" "Modified" "-"] [12-Mar-2010/22:36:44 "BrianH" "Code " "Modified" "-"] [12-Mar-2010/22:36:44 "BrianH" "Summary " "Modified" {All structured escape functions are disabled when they are called in an expression that accepts error! values => Unwind functions don't propagate when called in function arg expression that accepts error! values}] [12-Mar-2010/22:36:44 "BrianH" "Description " "Modified" "-"] [12-Mar-2010/22:25:38 "BrianH" "Comment : 0002092" "Modified" "-"] [12-Mar-2010/18:37 "BrianH" "Comment : 0002092" "Added" "-"] [12-Mar-2010/10:32:16 "Ladislav" "Comment : 0002090" "Added" "-"] [12-Mar-2010/10:31:23 "Ladislav" "Comment : 0002080" "Modified" "-"] [11-Mar-2010/10:23:16 "sunanda" "Comment : 0002087" "Added" "-"] [9-Mar-2010/12:35:47 "BrianH" "Comment : 0002082" "Modified" "-"] [9-Mar-2010/12:35:12 "BrianH" "Priority " "Modified" "normal => high"] [9-Mar-2010/12:34:52 "BrianH" "Comment : 0002082" "Added" "-"] [9-Mar-2010/10:51:38 "Ladislav" "Comment : 0002080" "Added" "-"] [9-Mar-2010/10:50:32 "Ladislav" "Comment : 0002073" "Modified" "-"] [8-Mar-2010/15:39:39 "Ladislav" "Comment : 0002073" "Added" "-"] [8-Mar-2010/15:19:42 "Ladislav" "Comment : 0002068" "Removed" "-"] [7-Mar-2010/21:57:17 "BrianH" "Comment : 0002070" "Added" "-"] [7-Mar-2010/21:56:21 "BrianH" "Code " "Modified" "-"] [7-Mar-2010/21:56:21 "BrianH" "Description " "Modified" "-"] [4-Mar-2010/9:54:51 "Ladislav" "Comment : 0002068" "Modified" "-"] [4-Mar-2010/9:54:32 "Ladislav" "Comment : 0002068" "Added" "-"] [4-Mar-2010/9:53:04 "Ladislav" "Comment : 0002067" "Removed" "-"] [4-Mar-2010/9:48:44 "Ladislav" "Comment : 0002067" "Added" "-"] [4-Mar-2010/9:45:37 "Ladislav" "Comment : 0002066" "Removed" "-"] [4-Mar-2010/9:43:35 "Ladislav" "Comment : 0002066" "Added" "-"] [3-Mar-2010/22:55:03 "BrianH" "Description " "Modified" "-"] [3-Mar-2010/22:53:03 "BrianH" "Description " "Modified" "-"] [3-Mar-2010/22:52:03 "BrianH" "Description " "Modified" "-"] [3-Mar-2010/22:21:02 "BrianH" "Code " "Modified" "-"] [3-Mar-2010/22:21:02 "BrianH" "Description " "Modified" "-"] [3-Mar-2010/22:21:02 "BrianH" "Summary " "Modified" {All structured escape functions are disabled when they are in an expression that accepts error! values => All structured escape functions are disabled when they are called in an expression that accepts error! values}] [3-Mar-2010/22:20:31 "BrianH" "Ticket " "Added" "-"] ] ]]