ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:99499] [Ruby master Bug#17105] A single `return` can return to two different places in a proc inside a lambda inside a method
@ 2020-08-06 10:54 eregontp
  2020-08-06 11:00 ` [ruby-core:99500] " eregontp
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: eregontp @ 2020-08-06 10:54 UTC (permalink / raw)
  To: ruby-core

Issue #17105 has been reported by Eregon (Benoit Daloze).

----------------------------------------
Bug #17105: A single `return` can return to two different places in a proc inside a lambda inside a method
https://bugs.ruby-lang.org/issues/17105

* Author: Eregon (Benoit Daloze)
* Status: Open
* Priority: Normal
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
A single `return` in the source code might return to 2 different lexical places.
That seems wrong to me, as AFAIK all other control flow language constructs always jump to a single place.

```ruby
def m(call_proc)
  r = -> {
    # This single return in the source might exit the lambda or the method!
    proc = Proc.new { return :return }

    if call_proc
      proc.call
      :after_in_lambda
    else
      proc
    end
  }.call # returns here if call_proc

  if call_proc
    [:after_in_method, r]
  else
    r.call
    :never_reached
  end
end


p m(true)  # => [:after_in_method, :return]
p m(false) # :return
```

We're trying to figure out the semantics of `return` inside a proc in
https://github.com/oracle/truffleruby/issues/1488#issuecomment-669185675
and this behavior doesn't seem to make much sense.

@headius also seems to agree:
> I would consider that behavior to be incorrect; once the proc has escaped from the lambda, its return target is no longer valid. It should not return to a different place.
> https://github.com/jruby/jruby/issues/6350#issuecomment-669603740

So:
* is this behavior intentional? or is it a bug?
* what are actually the semantics of `return` inside a proc?

The semantics seem incredibly complicated to a point developers have no idea where `return` actually goes.
Also it must get even more complicated if one defines a `lambda` method as the block in `lambda { return }` is then non-deterministically a proc or lambda.



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [ruby-core:99500] [Ruby master Bug#17105] A single `return` can return to two different places in a proc inside a lambda inside a method
  2020-08-06 10:54 [ruby-core:99499] [Ruby master Bug#17105] A single `return` can return to two different places in a proc inside a lambda inside a method eregontp
@ 2020-08-06 11:00 ` eregontp
  2020-08-06 14:34 ` [ruby-core:99502] " hanmac
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: eregontp @ 2020-08-06 11:00 UTC (permalink / raw)
  To: ruby-core

Issue #17105 has been updated by Eregon (Benoit Daloze).


I should also note some of these semantics might significantly harm the performance of Ruby.
CRuby seems to walk the stack on every `return`.
On others VMs there need to be some extra logic to find if the frame to return to is still on the stack.
It's already quite complicated but then if `return` can go to two places, it becomes a huge mess.

----------------------------------------
Bug #17105: A single `return` can return to two different places in a proc inside a lambda inside a method
https://bugs.ruby-lang.org/issues/17105#change-86957

* Author: Eregon (Benoit Daloze)
* Status: Open
* Priority: Normal
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
A single `return` in the source code might return to 2 different lexical places.
That seems wrong to me, as AFAIK all other control flow language constructs always jump to a single place.

```ruby
def m(call_proc)
  r = -> {
    # This single return in the source might exit the lambda or the method!
    proc = Proc.new { return :return }

    if call_proc
      proc.call
      :after_in_lambda
    else
      proc
    end
  }.call # returns here if call_proc

  if call_proc
    [:after_in_method, r]
  else
    r.call
    :never_reached
  end
end


p m(true)  # => [:after_in_method, :return]
p m(false) # :return
```

We're trying to figure out the semantics of `return` inside a proc in
https://github.com/oracle/truffleruby/issues/1488#issuecomment-669185675
and this behavior doesn't seem to make much sense.

@headius also seems to agree:
> I would consider that behavior to be incorrect; once the proc has escaped from the lambda, its return target is no longer valid. It should not return to a different place.
> https://github.com/jruby/jruby/issues/6350#issuecomment-669603740

So:
* is this behavior intentional? or is it a bug?
* what are actually the semantics of `return` inside a proc?

The semantics seem incredibly complicated to a point developers have no idea where `return` actually goes.
Also it must get even more complicated if one defines a `lambda` method as the block in `lambda { return }` is then non-deterministically a proc or lambda.



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [ruby-core:99502] [Ruby master Bug#17105] A single `return` can return to two different places in a proc inside a lambda inside a method
  2020-08-06 10:54 [ruby-core:99499] [Ruby master Bug#17105] A single `return` can return to two different places in a proc inside a lambda inside a method eregontp
  2020-08-06 11:00 ` [ruby-core:99500] " eregontp
@ 2020-08-06 14:34 ` hanmac
  2020-08-06 14:43 ` [ruby-core:99503] " chris
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: hanmac @ 2020-08-06 14:34 UTC (permalink / raw)
  To: ruby-core

Issue #17105 has been updated by Hanmac (Hans Mackowiak).


i think this is by design:

https://www.rubyguides.com/2016/02/ruby-procs-and-lambdas/

> A lambda will return normally, like a regular method.
> But a proc will try to return from the current context.

> Procs return from the current method, while lambdas return from the lambda itself.

----------------------------------------
Bug #17105: A single `return` can return to two different places in a proc inside a lambda inside a method
https://bugs.ruby-lang.org/issues/17105#change-86959

* Author: Eregon (Benoit Daloze)
* Status: Open
* Priority: Normal
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
A single `return` in the source code might return to 2 different lexical places.
That seems wrong to me, as AFAIK all other control flow language constructs always jump to a single place.

```ruby
def m(call_proc)
  r = -> {
    # This single return in the source might exit the lambda or the method!
    proc = Proc.new { return :return }

    if call_proc
      proc.call
      :after_in_lambda
    else
      proc
    end
  }.call # returns here if call_proc

  if call_proc
    [:after_in_method, r]
  else
    r.call
    :never_reached
  end
end


p m(true)  # => [:after_in_method, :return]
p m(false) # :return
```

We're trying to figure out the semantics of `return` inside a proc in
https://github.com/oracle/truffleruby/issues/1488#issuecomment-669185675
and this behavior doesn't seem to make much sense.

@headius also seems to agree:
> I would consider that behavior to be incorrect; once the proc has escaped from the lambda, its return target is no longer valid. It should not return to a different place.
> https://github.com/jruby/jruby/issues/6350#issuecomment-669603740

So:
* is this behavior intentional? or is it a bug?
* what are actually the semantics of `return` inside a proc?

The semantics seem incredibly complicated to a point developers have no idea where `return` actually goes.
Also it must get even more complicated if one defines a `lambda` method as the block in `lambda { return }` is then non-deterministically a proc or lambda.



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [ruby-core:99503] [Ruby master Bug#17105] A single `return` can return to two different places in a proc inside a lambda inside a method
  2020-08-06 10:54 [ruby-core:99499] [Ruby master Bug#17105] A single `return` can return to two different places in a proc inside a lambda inside a method eregontp
  2020-08-06 11:00 ` [ruby-core:99500] " eregontp
  2020-08-06 14:34 ` [ruby-core:99502] " hanmac
@ 2020-08-06 14:43 ` chris
  2020-08-06 19:09 ` [ruby-core:99504] " daniel
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: chris @ 2020-08-06 14:43 UTC (permalink / raw)
  To: ruby-core

Issue #17105 has been updated by chrisseaton (Chris Seaton).


Hans I don't think anyone is debating the basic idea of what return in a proc or lambda does - I think we're talking about the edge-case for a proc in a return in the example above, which isn't explained by the text you have.

----------------------------------------
Bug #17105: A single `return` can return to two different places in a proc inside a lambda inside a method
https://bugs.ruby-lang.org/issues/17105#change-86960

* Author: Eregon (Benoit Daloze)
* Status: Open
* Priority: Normal
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
A single `return` in the source code might return to 2 different lexical places.
That seems wrong to me, as AFAIK all other control flow language constructs always jump to a single place.

```ruby
def m(call_proc)
  r = -> {
    # This single return in the source might exit the lambda or the method!
    proc = Proc.new { return :return }

    if call_proc
      proc.call
      :after_in_lambda
    else
      proc
    end
  }.call # returns here if call_proc

  if call_proc
    [:after_in_method, r]
  else
    r.call
    :never_reached
  end
end


p m(true)  # => [:after_in_method, :return]
p m(false) # :return
```

We're trying to figure out the semantics of `return` inside a proc in
https://github.com/oracle/truffleruby/issues/1488#issuecomment-669185675
and this behavior doesn't seem to make much sense.

@headius also seems to agree:
> I would consider that behavior to be incorrect; once the proc has escaped from the lambda, its return target is no longer valid. It should not return to a different place.
> https://github.com/jruby/jruby/issues/6350#issuecomment-669603740

So:
* is this behavior intentional? or is it a bug?
* what are actually the semantics of `return` inside a proc?

The semantics seem incredibly complicated to a point developers have no idea where `return` actually goes.
Also it must get even more complicated if one defines a `lambda` method as the block in `lambda { return }` is then non-deterministically a proc or lambda.



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [ruby-core:99504] [Ruby master Bug#17105] A single `return` can return to two different places in a proc inside a lambda inside a method
  2020-08-06 10:54 [ruby-core:99499] [Ruby master Bug#17105] A single `return` can return to two different places in a proc inside a lambda inside a method eregontp
                   ` (2 preceding siblings ...)
  2020-08-06 14:43 ` [ruby-core:99503] " chris
@ 2020-08-06 19:09 ` daniel
  2020-08-06 23:47 ` [ruby-core:99505] " eregontp
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: daniel @ 2020-08-06 19:09 UTC (permalink / raw)
  To: ruby-core

Issue #17105 has been updated by Dan0042 (Daniel DeLorme).


I think the behavior makes sense to some extent, because the proc is within 2 nested contexts. Since the proc is within the lambda context, calling it in the lambda returns from the lambda. And since the proc is _also_ within the method context, calling it in the method returns from the method.

The `call_proc` branching logic makes this look more complicated than it really is, but if you separate the logic I feel the behavior is rather reasonable. What do you think should be the behavior of `m2` below?

```ruby
def m1
  r = -> {
    proc = Proc.new{ return :return }
    proc.call #return from lambda
    :after_in_lambda
  }.call
 
  [:after_in_method, r]
end

def m2
  r = -> {
    proc = Proc.new { return :return }
  }.call

  r.call #return from method
  :never_reached
end

p m1 #=> [:after_in_method, :return]
p m2 #=> :return
```


----------------------------------------
Bug #17105: A single `return` can return to two different places in a proc inside a lambda inside a method
https://bugs.ruby-lang.org/issues/17105#change-86961

* Author: Eregon (Benoit Daloze)
* Status: Open
* Priority: Normal
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
A single `return` in the source code might return to 2 different lexical places.
That seems wrong to me, as AFAIK all other control flow language constructs always jump to a single place.

```ruby
def m(call_proc)
  r = -> {
    # This single return in the source might exit the lambda or the method!
    proc = Proc.new { return :return }

    if call_proc
      proc.call
      :after_in_lambda
    else
      proc
    end
  }.call # returns here if call_proc

  if call_proc
    [:after_in_method, r]
  else
    r.call
    :never_reached
  end
end


p m(true)  # => [:after_in_method, :return]
p m(false) # :return
```

We're trying to figure out the semantics of `return` inside a proc in
https://github.com/oracle/truffleruby/issues/1488#issuecomment-669185675
and this behavior doesn't seem to make much sense.

@headius also seems to agree:
> I would consider that behavior to be incorrect; once the proc has escaped from the lambda, its return target is no longer valid. It should not return to a different place.
> https://github.com/jruby/jruby/issues/6350#issuecomment-669603740

So:
* is this behavior intentional? or is it a bug?
* what are actually the semantics of `return` inside a proc?

The semantics seem incredibly complicated to a point developers have no idea where `return` actually goes.
Also it must get even more complicated if one defines a `lambda` method as the block in `lambda { return }` is then non-deterministically a proc or lambda.



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [ruby-core:99505] [Ruby master Bug#17105] A single `return` can return to two different places in a proc inside a lambda inside a method
  2020-08-06 10:54 [ruby-core:99499] [Ruby master Bug#17105] A single `return` can return to two different places in a proc inside a lambda inside a method eregontp
                   ` (3 preceding siblings ...)
  2020-08-06 19:09 ` [ruby-core:99504] " daniel
@ 2020-08-06 23:47 ` eregontp
  2020-08-09 10:41 ` [ruby-core:99524] " shyouhei
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: eregontp @ 2020-08-06 23:47 UTC (permalink / raw)
  To: ruby-core

Issue #17105 has been updated by Eregon (Benoit Daloze).


IMHO it should be a LocalJumpError. The Proc should return to the lambda, that's syntactically the closest scope it should return to.
Since it's not possible to return it (the lambda is no longer on stack), it should be a LocalJumpError.

----------------------------------------
Bug #17105: A single `return` can return to two different places in a proc inside a lambda inside a method
https://bugs.ruby-lang.org/issues/17105#change-86962

* Author: Eregon (Benoit Daloze)
* Status: Open
* Priority: Normal
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
A single `return` in the source code might return to 2 different lexical places.
That seems wrong to me, as AFAIK all other control flow language constructs always jump to a single place.

```ruby
def m(call_proc)
  r = -> {
    # This single return in the source might exit the lambda or the method!
    proc = Proc.new { return :return }

    if call_proc
      proc.call
      :after_in_lambda
    else
      proc
    end
  }.call # returns here if call_proc

  if call_proc
    [:after_in_method, r]
  else
    r.call
    :never_reached
  end
end


p m(true)  # => [:after_in_method, :return]
p m(false) # :return
```

We're trying to figure out the semantics of `return` inside a proc in
https://github.com/oracle/truffleruby/issues/1488#issuecomment-669185675
and this behavior doesn't seem to make much sense.

@headius also seems to agree:
> I would consider that behavior to be incorrect; once the proc has escaped from the lambda, its return target is no longer valid. It should not return to a different place.
> https://github.com/jruby/jruby/issues/6350#issuecomment-669603740

So:
* is this behavior intentional? or is it a bug?
* what are actually the semantics of `return` inside a proc?

The semantics seem incredibly complicated to a point developers have no idea where `return` actually goes.
Also it must get even more complicated if one defines a `lambda` method as the block in `lambda { return }` is then non-deterministically a proc or lambda.



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [ruby-core:99524] [Ruby master Bug#17105] A single `return` can return to two different places in a proc inside a lambda inside a method
  2020-08-06 10:54 [ruby-core:99499] [Ruby master Bug#17105] A single `return` can return to two different places in a proc inside a lambda inside a method eregontp
                   ` (4 preceding siblings ...)
  2020-08-06 23:47 ` [ruby-core:99505] " eregontp
@ 2020-08-09 10:41 ` shyouhei
  2020-08-12 21:29 ` [ruby-core:99574] " headius
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: shyouhei @ 2020-08-09 10:41 UTC (permalink / raw)
  To: ruby-core

Issue #17105 has been updated by shyouhei (Shyouhei Urabe).


+1 to @eregon ’s interpretation.  Current behaviour is at least very cryptic.

----------------------------------------
Bug #17105: A single `return` can return to two different places in a proc inside a lambda inside a method
https://bugs.ruby-lang.org/issues/17105#change-86984

* Author: Eregon (Benoit Daloze)
* Status: Open
* Priority: Normal
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
A single `return` in the source code might return to 2 different lexical places.
That seems wrong to me, as AFAIK all other control flow language constructs always jump to a single place.

```ruby
def m(call_proc)
  r = -> {
    # This single return in the source might exit the lambda or the method!
    proc = Proc.new { return :return }

    if call_proc
      proc.call
      :after_in_lambda
    else
      proc
    end
  }.call # returns here if call_proc

  if call_proc
    [:after_in_method, r]
  else
    r.call
    :never_reached
  end
end


p m(true)  # => [:after_in_method, :return]
p m(false) # :return
```

We're trying to figure out the semantics of `return` inside a proc in
https://github.com/oracle/truffleruby/issues/1488#issuecomment-669185675
and this behavior doesn't seem to make much sense.

@headius also seems to agree:
> I would consider that behavior to be incorrect; once the proc has escaped from the lambda, its return target is no longer valid. It should not return to a different place.
> https://github.com/jruby/jruby/issues/6350#issuecomment-669603740

So:
* is this behavior intentional? or is it a bug?
* what are actually the semantics of `return` inside a proc?

The semantics seem incredibly complicated to a point developers have no idea where `return` actually goes.
Also it must get even more complicated if one defines a `lambda` method as the block in `lambda { return }` is then non-deterministically a proc or lambda.



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [ruby-core:99574] [Ruby master Bug#17105] A single `return` can return to two different places in a proc inside a lambda inside a method
  2020-08-06 10:54 [ruby-core:99499] [Ruby master Bug#17105] A single `return` can return to two different places in a proc inside a lambda inside a method eregontp
                   ` (5 preceding siblings ...)
  2020-08-09 10:41 ` [ruby-core:99524] " shyouhei
@ 2020-08-12 21:29 ` headius
  2020-08-31  9:00 ` [ruby-core:99794] " matz
  2021-02-25  2:22 ` [ruby-core:102600] " merch-redmine
  8 siblings, 0 replies; 10+ messages in thread
From: headius @ 2020-08-12 21:29 UTC (permalink / raw)
  To: ruby-core

Issue #17105 has been updated by headius (Charles Nutter).


Just to be clear I am +1 on single return target, as described here: https://github.com/jruby/jruby/issues/6350#issuecomment-669603740

In addition to the confusing (and possibly inefficient) behavior that results from having two possible return targets, there's also a bug potential here if someone "accidentally" allows a proc containing a return to escape from its lambda container. Rather than returning from the lambda as it should have done, it will now return from the next "returnable" scope, and likely interrupt execution in an unexpected way.

I would challenge anyone to explain why the current behavior *should* exist, since I can't think of a single valid use case. If there's no use case for a confusing "feature", we should remove it.

----------------------------------------
Bug #17105: A single `return` can return to two different places in a proc inside a lambda inside a method
https://bugs.ruby-lang.org/issues/17105#change-87042

* Author: Eregon (Benoit Daloze)
* Status: Open
* Priority: Normal
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
A single `return` in the source code might return to 2 different lexical places.
That seems wrong to me, as AFAIK all other control flow language constructs always jump to a single place.

```ruby
def m(call_proc)
  r = -> {
    # This single return in the source might exit the lambda or the method!
    proc = Proc.new { return :return }

    if call_proc
      proc.call
      :after_in_lambda
    else
      proc
    end
  }.call # returns here if call_proc

  if call_proc
    [:after_in_method, r]
  else
    r.call
    :never_reached
  end
end


p m(true)  # => [:after_in_method, :return]
p m(false) # :return
```

We're trying to figure out the semantics of `return` inside a proc in
https://github.com/oracle/truffleruby/issues/1488#issuecomment-669185675
and this behavior doesn't seem to make much sense.

@headius also seems to agree:
> I would consider that behavior to be incorrect; once the proc has escaped from the lambda, its return target is no longer valid. It should not return to a different place.
> https://github.com/jruby/jruby/issues/6350#issuecomment-669603740

So:
* is this behavior intentional? or is it a bug?
* what are actually the semantics of `return` inside a proc?

The semantics seem incredibly complicated to a point developers have no idea where `return` actually goes.
Also it must get even more complicated if one defines a `lambda` method as the block in `lambda { return }` is then non-deterministically a proc or lambda.



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [ruby-core:99794] [Ruby master Bug#17105] A single `return` can return to two different places in a proc inside a lambda inside a method
  2020-08-06 10:54 [ruby-core:99499] [Ruby master Bug#17105] A single `return` can return to two different places in a proc inside a lambda inside a method eregontp
                   ` (6 preceding siblings ...)
  2020-08-12 21:29 ` [ruby-core:99574] " headius
@ 2020-08-31  9:00 ` matz
  2021-02-25  2:22 ` [ruby-core:102600] " merch-redmine
  8 siblings, 0 replies; 10+ messages in thread
From: matz @ 2020-08-31  9:00 UTC (permalink / raw)
  To: ruby-core

Issue #17105 has been updated by matz (Yukihiro Matsumoto).


It is intentional since 1.6.0. But I am OK with making `m2` raise `LocalJumpError`.
Ask @ko1 about migration.

Matz.


----------------------------------------
Bug #17105: A single `return` can return to two different places in a proc inside a lambda inside a method
https://bugs.ruby-lang.org/issues/17105#change-87311

* Author: Eregon (Benoit Daloze)
* Status: Open
* Priority: Normal
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
A single `return` in the source code might return to 2 different lexical places.
That seems wrong to me, as AFAIK all other control flow language constructs always jump to a single place.

```ruby
def m(call_proc)
  r = -> {
    # This single return in the source might exit the lambda or the method!
    proc = Proc.new { return :return }

    if call_proc
      proc.call
      :after_in_lambda
    else
      proc
    end
  }.call # returns here if call_proc

  if call_proc
    [:after_in_method, r]
  else
    r.call
    :never_reached
  end
end


p m(true)  # => [:after_in_method, :return]
p m(false) # :return
```

We're trying to figure out the semantics of `return` inside a proc in
https://github.com/oracle/truffleruby/issues/1488#issuecomment-669185675
and this behavior doesn't seem to make much sense.

@headius also seems to agree:
> I would consider that behavior to be incorrect; once the proc has escaped from the lambda, its return target is no longer valid. It should not return to a different place.
> https://github.com/jruby/jruby/issues/6350#issuecomment-669603740

So:
* is this behavior intentional? or is it a bug?
* what are actually the semantics of `return` inside a proc?

The semantics seem incredibly complicated to a point developers have no idea where `return` actually goes.
Also it must get even more complicated if one defines a `lambda` method as the block in `lambda { return }` is then non-deterministically a proc or lambda.



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [ruby-core:102600] [Ruby master Bug#17105] A single `return` can return to two different places in a proc inside a lambda inside a method
  2020-08-06 10:54 [ruby-core:99499] [Ruby master Bug#17105] A single `return` can return to two different places in a proc inside a lambda inside a method eregontp
                   ` (7 preceding siblings ...)
  2020-08-31  9:00 ` [ruby-core:99794] " matz
@ 2021-02-25  2:22 ` merch-redmine
  8 siblings, 0 replies; 10+ messages in thread
From: merch-redmine @ 2021-02-25  2:22 UTC (permalink / raw)
  To: ruby-core

Issue #17105 has been updated by jeremyevans0 (Jeremy Evans).


I added a pull request to fix this: https://github.com/ruby/ruby/pull/4223

----------------------------------------
Bug #17105: A single `return` can return to two different places in a proc inside a lambda inside a method
https://bugs.ruby-lang.org/issues/17105#change-90583

* Author: Eregon (Benoit Daloze)
* Status: Open
* Priority: Normal
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN
----------------------------------------
A single `return` in the source code might return to 2 different lexical places.
That seems wrong to me, as AFAIK all other control flow language constructs always jump to a single place.

```ruby
def m(call_proc)
  r = -> {
    # This single return in the source might exit the lambda or the method!
    proc = Proc.new { return :return }

    if call_proc
      proc.call
      :after_in_lambda
    else
      proc
    end
  }.call # returns here if call_proc

  if call_proc
    [:after_in_method, r]
  else
    r.call
    :never_reached
  end
end


p m(true)  # => [:after_in_method, :return]
p m(false) # :return
```

We're trying to figure out the semantics of `return` inside a proc in
https://github.com/oracle/truffleruby/issues/1488#issuecomment-669185675
and this behavior doesn't seem to make much sense.

@headius also seems to agree:
> I would consider that behavior to be incorrect; once the proc has escaped from the lambda, its return target is no longer valid. It should not return to a different place.
> https://github.com/jruby/jruby/issues/6350#issuecomment-669603740

So:
* is this behavior intentional? or is it a bug?
* what are actually the semantics of `return` inside a proc?

The semantics seem incredibly complicated to a point developers have no idea where `return` actually goes.
Also it must get even more complicated if one defines a `lambda` method as the block in `lambda { return }` is then non-deterministically a proc or lambda.



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2021-02-25  2:22 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-06 10:54 [ruby-core:99499] [Ruby master Bug#17105] A single `return` can return to two different places in a proc inside a lambda inside a method eregontp
2020-08-06 11:00 ` [ruby-core:99500] " eregontp
2020-08-06 14:34 ` [ruby-core:99502] " hanmac
2020-08-06 14:43 ` [ruby-core:99503] " chris
2020-08-06 19:09 ` [ruby-core:99504] " daniel
2020-08-06 23:47 ` [ruby-core:99505] " eregontp
2020-08-09 10:41 ` [ruby-core:99524] " shyouhei
2020-08-12 21:29 ` [ruby-core:99574] " headius
2020-08-31  9:00 ` [ruby-core:99794] " matz
2021-02-25  2:22 ` [ruby-core:102600] " merch-redmine

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).