Bug #3011
closedcaller for recursive function
Description
=begin
For some reason, Ruby 1.8 will skip multiple copies of the same method. In case of a recursive function call, the behavior is different from Ruby 1.9 and seems wrong.
Here's the rubyspec I just committed:
it "returns one entry per call, even for recursive methods" do
def recurse(n)
return caller if n <= 0
recurse(n-1)
end
(recurse(3).size - recurse(2).size).should == 1
end
The following patch doesn't seem to yield any new failure with make test, make test-all, nor the caller specs:
diff --git a/eval.c b/eval.c
index 3407548..65fb970 100644
--- a/eval.c
+++ b/eval.c
@@ -6468,9 +6468,6 @@ backtrace(lev)
}
for (; frame && (n = frame->node); frame = frame->prev) {
if (frame->prev && frame->prev->last_func) {
-
if (frame->prev->node == n) {
-
if (frame->prev->last_func == frame->last_func) continue;
-
} snprintf(buf, BUFSIZ, "%s:%d:in `%s'", n->nd_file, nd_line(n), rb_id2name(frame->prev->last_func));
Nobu, can you recall what was the reason for these lines ( r10593 ) ?
=end
Updated by nobu (Nobuyoshi Nakada) over 14 years ago
=begin
Hi,
At Thu, 25 Mar 2010 10:38:57 +0900,
Marc-Andre Lafortune wrote in [ruby-core:28963]:
For some reason, Ruby 1.8 will skip multiple copies of the
same method. In case of a recursive function call, the
behavior is different from Ruby 1.9 and seems wrong.
According to the log and ML archive, it was origined from
r8590, and intended to veil implicitly called method names.
e.g.: to make the former to the latter.
$ ruby -e 'p [0].max_by'
-e:1:in max_by': no block given (LocalJumpError) from -e:1:in
each'
from -e:1:in `max_by'
from -e:1
$ ruby -e 'p [0].max_by'
-e:1:in `max_by': no block given (LocalJumpError)
from -e:1
But something seems to have changed and it doesn't work
expectedly now.
The following patch doesn't seem to yield any new failure
with make test, make test-all, nor the caller specs:
Seems nice.
Another idea is to reduce same methods like following patch,
but it may cause other issues.
diff --git i/eval.c w/eval.c
index 3407548..159ed0e 100644
--- i/eval.c
+++ w/eval.c
@@ -6437,4 +6437,5 @@ backtrace(lev)
VALUE ary;
NODE *n;
-
int succ = 0;
ary = rb_ary_new();
@@ -6467,15 +6468,22 @@ backtrace(lev)
}
}
- for (; frame && (n = frame->node); frame = frame->prev) {
- for (frame && (n = frame->node); frame = frame->prev) {
- const char *name = 0;
if (frame->prev && frame->prev->last_func) {
-
if (frame->prev->node == n) {
-
if (frame->prev->last_func == frame->last_func) continue;
-
if (frame->prev->node == n && frame->prev->last_func == frame->last_func) {
-
succ++;
-
continue; }
-
snprintf(buf, BUFSIZ, "%s:%d:in `%s'",
-
n->nd_file, nd_line(n),
-
rb_id2name(frame->prev->last_func));
-
}name = rb_id2name(frame->prev->last_func);
- else {
-
snprintf(buf, BUFSIZ, "%s:%d", n->nd_file, nd_line(n));
- snprintf(buf, BUFSIZ, "%s:%d", n->nd_file, nd_line(n));
- if (name) {
-
long len = strlen(buf);
-
snprintf(buf + len, BUFSIZ - len, ":in `%s'", name);
-
len += strlen(buf + len);
-
if (succ > 0) {
-
snprintf(buf + len, BUFSIZ - len, " (%d levels)", succ + 1);
-
succ = 0;
-
}}
rb_ary_push(ary, rb_str_new2(buf));
--
Nobu Nakada
=end
Updated by shyouhei (Shyouhei Urabe) about 14 years ago
- Status changed from Open to Assigned
=begin
=end
Updated by marcandre (Marc-Andre Lafortune) over 12 years ago
- Description updated (diff)
- Status changed from Assigned to Closed