Bug #13564
closedException message management
Description
We can modify Exception#message if given String is not frozen.
Should we continue this specification?
Now, we can modify exception message with message string modification.
However, if we pass frozen string, it is not allowed.
begin
raise 'foo'.freeze
ensure
$!.message.replace 'bar' #=> `replace': can't modify frozen String (RuntimeError)
end
Furthermore, # frozen_string_literal: true freeze all of string literals.
# frozen_string_literal: true
begin
raise 'foo'
ensure
$!.message.replace 'bar' #=> `replace': can't modify frozen String (RuntimeError)
end
Background and motivation¶
I want to add Exception message on ensure clause like the code in previous section. Just now, we need to re-raise another exception (with raise($!.class, new_msg, $!.backtrace)). I tried to modify $!.message and it works on small script. However, I try it on production (*1), it doesn't work because of frozen_string_literal: true.
I think current behavior (specification?) is easy to misusing.
Ideas¶
- (1) To prevent such behavior
- (1-1) Freeze message strings at initialize
- (1-2) Return copy string at
Exception#message
- (2) Provide
Exception#message =- And (1-1) or (1-2)
- (3) Allow such behavior. If a frozen message is given, dup it and set as modifiable.
Updated by Eregon (Benoit Daloze) over 9 years ago
I think using Exception#cause for this would be a better way to address this problem.
However, there is a long-standing bug of the cause not being shown in Exception#inspect and neither by the top-level handler: https://bugs.ruby-lang.org/issues/9918
@ko1 (Koichi Sasada): Could you share your use-case? Modifying an exception message in ensure seems unusual to me.
In the test_gem_gem_runner.rb, it seems rescue Exception would be more intuitive to handle this (but it has the same problem about modifying the message).
Otherwise I think 1-1 + 2 is the best compromise.
Updated by ko1 (Koichi Sasada) over 9 years ago
On 2017/05/15 20:31, eregontp@gmail.com wrote:
I think using Exception#cause for this would be a better way to address this problem.
However, there is a long-standing bug of the cause not being shown in Exception#inspect and neither by the top-level handler: https://bugs.ruby-lang.org/issues/9918
I agree it is one solution. However, to make sure transparency (for
rescue clause which catch the exception later) we need to provide same
error class ($!.class).
@ko1 (Koichi Sasada): Could you share your use-case? Modifying an exception message in ensure seems unusual to me.
In the test_gem_gem_runner.rb, it seemsrescue Exceptionwould be more intuitive to handle this (but it has the same problem about modifying the message).
My usage is a bit strange. I want to know the status about just before
suspicious code (require 'rubygems/gem_runner') and just after this
line if $! is not nil. Usually we can show such information on STDERR
but test framework (test-all with parallel option) hides all of STDERR
output so that we need to show via Exception message.
I think such usage is not so frequent so that
Otherwise I think 1-1 + 2 is the best compromise.
I think (1) without (2) (with [Feature #9918]) is acceptable.
Thanks,
Koichi¶
// SASADA Koichi at atdot dot net
Updated by matz (Yukihiro Matsumoto) about 9 years ago
I understand the principle. But I think it's a programmer's fault to modify the string.
I don't think it's worth prohibiting (and making implementation more complex).
Matz.
Updated by naruse (Yui NARUSE) about 9 years ago
Updated by jeremyevans0 (Jeremy Evans) about 7 years ago
- Status changed from Open to Rejected