ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:119637] Behavior of raising from rescue blocks when multiple rescue blocks exist
@ 2024-10-29 12:42 Rodrigo Rosenfeld Rosas via ruby-core
  2024-10-29 18:07 ` [ruby-core:119639] " Austin Ziegler via ruby-core
  0 siblings, 1 reply; 3+ messages in thread
From: Rodrigo Rosenfeld Rosas via ruby-core @ 2024-10-29 12:42 UTC (permalink / raw)
  To: ruby-core; +Cc: Rodrigo Rosenfeld Rosas


[-- Attachment #1.1: Type: text/plain, Size: 1759 bytes --]

Hello, I couldn't find any documentation about the subject, so I thought
this behavior should be probably documented.

Given the following code:

def raise_error
  raise "runtime error message"
rescue => e
  "StandardError: #{e.message}"
rescue RuntimeError => e
  puts "RuntimeError raised: #{e.message}"
  raise StandardError, "standard error message"
end

# same, but the order of the rescue blocks are inverted
def raise_error2
  raise "runtime error message"
rescue RuntimeError => e
  puts "RuntimeError raised: #{e.message}"
  raise StandardError, "standard error message"
rescue => e
  "StandardError: #{e.message}"
end

p ["raise_error", raise_error ]

begin
  p ["raise_error2", raise_error2]
rescue => e
  puts "raise_error2 raised: #{e.message}"
end

When we run it, this is the output in Ruby 3.3.5:

["raise_error", "StandardError: runtime error message"]

RuntimeError raised: runtime error message

raise_error2 raised: standard error message


In the first case (raise_error), the code raised from the RuntimeError
rescue block is rescued by the StandardError block, but when inverting the
order of the rescue blocks (raise_error2) then this won't happen.

Is this part of the specs? Is this behavior documented somewhere? Could
this behavior differ in different Ruby implementations and versions? Or can
we rely on such behavior?


This chapter doesn't include such case in its examples:

https://ruby-doc.com/docs/ProgrammingRuby/html/tut_exceptions.html

Or this documentation about Exceptions:

https://ruby-doc.org/3.3.5/syntax/exceptions_rdoc.html

Is there a recommended way for wrapping exceptions into a particular one
and then handling that exception from within the same method rescue blocks?
Or is this considered a bad practice?

[-- Attachment #1.2: Type: text/html, Size: 5138 bytes --]

[-- Attachment #2: Type: text/plain, Size: 254 bytes --]

 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/

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

* [ruby-core:119639] Re: Behavior of raising from rescue blocks when multiple rescue blocks exist
  2024-10-29 12:42 [ruby-core:119637] Behavior of raising from rescue blocks when multiple rescue blocks exist Rodrigo Rosenfeld Rosas via ruby-core
@ 2024-10-29 18:07 ` Austin Ziegler via ruby-core
  2024-10-29 19:22   ` [ruby-core:119640] " Rodrigo Rosenfeld Rosas via ruby-core
  0 siblings, 1 reply; 3+ messages in thread
From: Austin Ziegler via ruby-core @ 2024-10-29 18:07 UTC (permalink / raw)
  To: Ruby developers; +Cc: Rodrigo Rosenfeld Rosas, Austin Ziegler


[-- Attachment #1.1: Type: text/plain, Size: 11430 bytes --]

RuntimeError is a descendant of StandardError, and rescues happen exactly
once per exception handling block.

That is, your first code example will never hit RuntimeError because it's
swallowed by the implicit StandardError.

Here's a class tree of Exception from my local irb:

- Exception
    |- ErrorHighlight::Spotter::NonAscii
    |- IRB::Abort
    |- IRB::LoadAbort
    |- NoMemoryError
    |- ScriptError
    |    |- LoadError
    |    |    `- Gem::LoadError
    |    |         |- Gem::ConflictError
    |    |         `- Gem::MissingSpecError
    |    |              `- Gem::MissingSpecVersionError
    |    |- NotImplementedError
    |    `- SyntaxError
    |- SecurityError
    |- SignalException
    |    `- Interrupt
    |- StandardError
    |    |- ArgumentError
    |    |    |- Gem::Requirement::BadRequirementError
    |    |    |- IO::Buffer::MaskError
    |    |    `- UncaughtThrowError
    |    |- EncodingError
    |    |    |- Encoding::CompatibilityError
    |    |    |- Encoding::ConverterNotFoundError
    |    |    |- Encoding::InvalidByteSequenceError
    |    |    `- Encoding::UndefinedConversionError
    |    |- FiberError
    |    |- Fiddle::Error
    |    |    |- Fiddle::ClearedReferenceError
    |    |    `- Fiddle::DLError
    |    |- Gem::Molinillo::ResolverError
    |    |    |- Gem::Molinillo::CircularDependencyError
    |    |    |- Gem::Molinillo::NoSuchDependencyError
    |    |    `- Gem::Molinillo::VersionConflict
    |    |- Gem::TSort::Cyclic
    |    |- IOError
    |    |    |- EOFError
    |    |    `- IO::TimeoutError
    |    |- IRB::CantChangeBinding
    |    |- IRB::CantReturnToNormalMode
    |    |- IRB::Command::CommandArgumentError
    |    |- IRB::IllegalParameter
    |    |- IRB::IrbAlreadyDead
    |    |- IRB::IrbSwitchedToCurrentThread
    |    |- IRB::NoSuchJob
    |    |- IRB::RubyLex::TerminateLineInput
    |    |- IRB::SourceFinder::EvaluationError
    |    |- IRB::UndefinedPromptMode
    |    |- IRB::UnrecognizedSwitch
    |    |- IndexError
    |    |    |- KeyError
    |    |    `- StopIteration
    |    |         |- ClosedQueueError
    |    |         `- Ractor::ClosedError
    |    |- JSON::JSONError
    |    |    |- JSON::GeneratorError
    |    |    |- JSON::MissingUnicodeSupport
    |    |    `- JSON::ParserError
    |    |         `- JSON::NestingError
    |    |              `- JSON::CircularDatastructure
    |    |- LocalJumpError
    |    |- Math::DomainError
    |    |- NameError
    |    |    `- NoMethodError
    |    |- NoMatchingPatternError
    |    |    `- NoMatchingPatternKeyError
    |    |- RangeError
    |    |    `- FloatDomainError
    |    |- RegexpError
    |    |    `- Regexp::TimeoutError
    |    |- Reline::ConfigEncodingConversionError
    |    |- Reline::Terminfo::TerminfoError
    |    |- Ripper::TokenPattern::Error
    |    |    |- Ripper::TokenPattern::CompileError
    |    |    `- Ripper::TokenPattern::MatchError
    |    |- RuntimeError
    |    |    |- FrozenError
    |    |    |- Gem::Exception
    |    |    |    |- Gem::CommandLineError
    |    |    |    |- Gem::DependencyError
    |    |    |    |    |- Gem::DependencyResolutionError
    |    |    |    |    `- Gem::UnsatisfiableDependencyError
    |    |    |    |- Gem::DependencyRemovalException
    |    |    |    |- Gem::DocumentError
    |    |    |    |- Gem::EndOfYAMLException
    |    |    |    |- Gem::FilePermissionError
    |    |    |    |- Gem::FormatException
    |    |    |    |- Gem::GemNotFoundException
    |    |    |    |    `- Gem::SpecificGemNotFoundException
    |    |    |    |- Gem::GemNotInHomeException
    |    |    |    |- Gem::ImpossibleDependenciesError
    |    |    |    |- Gem::InstallError
    |    |    |    |    `- Gem::RuntimeRequirementNotMetError
    |    |    |    |- Gem::InvalidSpecificationException
    |    |    |    |- Gem::OperationNotSupportedError
    |    |    |    |- Gem::RemoteError
    |    |    |    |- Gem::RemoteInstallationCancelled
    |    |    |    |- Gem::RemoteInstallationSkipped
    |    |    |    |- Gem::RemoteSourceException
    |    |    |    |- Gem::RequestSet::Lockfile::ParseError
    |    |    |    |- Gem::RubyVersionMismatch
    |    |    |    |- Gem::UninstallError
    |    |    |    |- Gem::UnknownCommandError
    |    |    |    |- Gem::VerificationError
    |    |    |    `- Gem::WebauthnVerificationError
    |    |    |- IO::Buffer::AccessError
    |    |    |- IO::Buffer::AllocationError
    |    |    |- IO::Buffer::InvalidatedError
    |    |    |- IO::Buffer::LockedError
    |    |    |- RDoc::Error
    |    |    |- Ractor::Error
    |    |    |    |- Ractor::IsolationError
    |    |    |    |- Ractor::MovedError
    |    |    |    |- Ractor::RemoteError
    |    |    |    `- Ractor::UnsafeError
    |    |    `- Reline::Config::InvalidInputrc
    |    |- SystemCallError
    |    |    |- Errno::E2BIG
    |    |    |- Errno::EACCES
    |    |    |- Errno::EADDRINUSE
    |    |    |- Errno::EADDRNOTAVAIL
    |    |    |- Errno::EAFNOSUPPORT
    |    |    |- Errno::EAGAIN
    |    |    |    |- IO::EAGAINWaitReadable
    |    |    |    `- IO::EAGAINWaitWritable
    |    |    |- Errno::EALREADY
    |    |    |- Errno::EAUTH
    |    |    |- Errno::EBADARCH
    |    |    |- Errno::EBADEXEC
    |    |    |- Errno::EBADF
    |    |    |- Errno::EBADMACHO
    |    |    |- Errno::EBADMSG
    |    |    |- Errno::EBADRPC
    |    |    |- Errno::EBUSY
    |    |    |- Errno::ECANCELED
    |    |    |- Errno::ECHILD
    |    |    |- Errno::ECONNABORTED
    |    |    |- Errno::ECONNREFUSED
    |    |    |- Errno::ECONNRESET
    |    |    |- Errno::EDEADLK
    |    |    |- Errno::EDESTADDRREQ
    |    |    |- Errno::EDEVERR
    |    |    |- Errno::EDOM
    |    |    |- Errno::EDQUOT
    |    |    |- Errno::EEXIST
    |    |    |- Errno::EFAULT
    |    |    |- Errno::EFBIG
    |    |    |- Errno::EFTYPE
    |    |    |- Errno::EHOSTDOWN
    |    |    |- Errno::EHOSTUNREACH
    |    |    |- Errno::EIDRM
    |    |    |- Errno::EILSEQ
    |    |    |- Errno::EINPROGRESS
    |    |    |    |- IO::EINPROGRESSWaitReadable
    |    |    |    `- IO::EINPROGRESSWaitWritable
    |    |    |- Errno::EINTR
    |    |    |- Errno::EINVAL
    |    |    |- Errno::EIO
    |    |    |- Errno::EISCONN
    |    |    |- Errno::EISDIR
    |    |    |- Errno::ELAST
    |    |    |- Errno::ELOOP
    |    |    |- Errno::EMFILE
    |    |    |- Errno::EMLINK
    |    |    |- Errno::EMSGSIZE
    |    |    |- Errno::EMULTIHOP
    |    |    |- Errno::ENAMETOOLONG
    |    |    |- Errno::ENEEDAUTH
    |    |    |- Errno::ENETDOWN
    |    |    |- Errno::ENETRESET
    |    |    |- Errno::ENETUNREACH
    |    |    |- Errno::ENFILE
    |    |    |- Errno::ENOATTR
    |    |    |- Errno::ENOBUFS
    |    |    |- Errno::ENODATA
    |    |    |- Errno::ENODEV
    |    |    |- Errno::ENOENT
    |    |    |- Errno::ENOEXEC
    |    |    |- Errno::ENOLCK
    |    |    |- Errno::ENOLINK
    |    |    |- Errno::ENOMEM
    |    |    |- Errno::ENOMSG
    |    |    |- Errno::ENOPOLICY
    |    |    |- Errno::ENOPROTOOPT
    |    |    |- Errno::ENOSPC
    |    |    |- Errno::ENOSR
    |    |    |- Errno::ENOSTR
    |    |    |- Errno::ENOSYS
    |    |    |- Errno::ENOTBLK
    |    |    |- Errno::ENOTCONN
    |    |    |- Errno::ENOTDIR
    |    |    |- Errno::ENOTEMPTY
    |    |    |- Errno::ENOTRECOVERABLE
    |    |    |- Errno::ENOTSOCK
    |    |    |- Errno::ENOTSUP
    |    |    |- Errno::ENOTTY
    |    |    |- Errno::ENXIO
    |    |    |- Errno::EOPNOTSUPP
    |    |    |- Errno::EOVERFLOW
    |    |    |- Errno::EOWNERDEAD
    |    |    |- Errno::EPERM
    |    |    |- Errno::EPFNOSUPPORT
    |    |    |- Errno::EPIPE
    |    |    |- Errno::EPROCLIM
    |    |    |- Errno::EPROCUNAVAIL
    |    |    |- Errno::EPROGMISMATCH
    |    |    |- Errno::EPROGUNAVAIL
    |    |    |- Errno::EPROTO
    |    |    |- Errno::EPROTONOSUPPORT
    |    |    |- Errno::EPROTOTYPE
    |    |    |- Errno::EPWROFF
    |    |    |- Errno::ERANGE
    |    |    |- Errno::EREMOTE
    |    |    |- Errno::EROFS
    |    |    |- Errno::ERPCMISMATCH
    |    |    |- Errno::ESHLIBVERS
    |    |    |- Errno::ESHUTDOWN
    |    |    |- Errno::ESOCKTNOSUPPORT
    |    |    |- Errno::ESPIPE
    |    |    |- Errno::ESRCH
    |    |    |- Errno::ESTALE
    |    |    |- Errno::ETIME
    |    |    |- Errno::ETIMEDOUT
    |    |    |- Errno::ETOOMANYREFS
    |    |    |- Errno::ETXTBSY
    |    |    |- Errno::EUSERS
    |    |    |- Errno::EXDEV
    |    |    `- Errno::NOERROR
    |    |- ThreadError
    |    |- TypeError
    |    `- ZeroDivisionError
    |- SystemExit
    |    `- Gem::SystemExitException
    |- SystemStackError
    `- fatal

-a

On Tue, Oct 29, 2024 at 8:48 AM Rodrigo Rosenfeld Rosas via ruby-core <
ruby-core@ml.ruby-lang.org> wrote:

> Hello, I couldn't find any documentation about the subject, so I thought
> this behavior should be probably documented.
>
> Given the following code:
>
> def raise_error
>   raise "runtime error message"
> rescue => e
>   "StandardError: #{e.message}"
> rescue RuntimeError => e
>   puts "RuntimeError raised: #{e.message}"
>   raise StandardError, "standard error message"
> end
>
> # same, but the order of the rescue blocks are inverted
> def raise_error2
>   raise "runtime error message"
> rescue RuntimeError => e
>   puts "RuntimeError raised: #{e.message}"
>   raise StandardError, "standard error message"
> rescue => e
>   "StandardError: #{e.message}"
> end
>
> p ["raise_error", raise_error ]
>
> begin
>   p ["raise_error2", raise_error2]
> rescue => e
>   puts "raise_error2 raised: #{e.message}"
> end
>
> When we run it, this is the output in Ruby 3.3.5:
>
> ["raise_error", "StandardError: runtime error message"]
>
> RuntimeError raised: runtime error message
>
> raise_error2 raised: standard error message
>
>
> In the first case (raise_error), the code raised from the RuntimeError
> rescue block is rescued by the StandardError block, but when inverting the
> order of the rescue blocks (raise_error2) then this won't happen.
>
> Is this part of the specs? Is this behavior documented somewhere? Could
> this behavior differ in different Ruby implementations and versions? Or can
> we rely on such behavior?
>
>
> This chapter doesn't include such case in its examples:
>
> https://ruby-doc.com/docs/ProgrammingRuby/html/tut_exceptions.html
>
> Or this documentation about Exceptions:
>
> https://ruby-doc.org/3.3.5/syntax/exceptions_rdoc.html
>
> Is there a recommended way for wrapping exceptions into a particular one
> and then handling that exception from within the same method rescue blocks?
> Or is this considered a bad practice?
>
>
>  ______________________________________________
>  ruby-core mailing list -- ruby-core@ml.ruby-lang.org
>  To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
>  ruby-core info --
> https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/



-- 
Austin Ziegler • halostatue@gmail.com • austin@halostatue.ca
http://www.halostatue.ca/http://twitter.com/halostatue

[-- Attachment #1.2: Type: text/html, Size: 17864 bytes --]

[-- Attachment #2: Type: text/plain, Size: 254 bytes --]

 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/

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

* [ruby-core:119640] Re: Behavior of raising from rescue blocks when multiple rescue blocks exist
  2024-10-29 18:07 ` [ruby-core:119639] " Austin Ziegler via ruby-core
@ 2024-10-29 19:22   ` Rodrigo Rosenfeld Rosas via ruby-core
  0 siblings, 0 replies; 3+ messages in thread
From: Rodrigo Rosenfeld Rosas via ruby-core @ 2024-10-29 19:22 UTC (permalink / raw)
  To: Austin Ziegler; +Cc: Ruby developers, Rodrigo Rosenfeld Rosas


[-- Attachment #1.1: Type: text/plain, Size: 12307 bytes --]

> rescues happen exactly once per exception handling block.

Awesome, great to know that and for the explanation on why both methods
yield different results. I totally forgot RuntimeError is an StandardError.

Em ter., 29 de out. de 2024 às 15:07, Austin Ziegler <halostatue@gmail.com>
escreveu:

> RuntimeError is a descendant of StandardError, and rescues happen exactly
> once per exception handling block.
>
> That is, your first code example will never hit RuntimeError because it's
> swallowed by the implicit StandardError.
>
> Here's a class tree of Exception from my local irb:
>
> - Exception
>     |- ErrorHighlight::Spotter::NonAscii
>     |- IRB::Abort
>     |- IRB::LoadAbort
>     |- NoMemoryError
>     |- ScriptError
>     |    |- LoadError
>     |    |    `- Gem::LoadError
>     |    |         |- Gem::ConflictError
>     |    |         `- Gem::MissingSpecError
>     |    |              `- Gem::MissingSpecVersionError
>     |    |- NotImplementedError
>     |    `- SyntaxError
>     |- SecurityError
>     |- SignalException
>     |    `- Interrupt
>     |- StandardError
>     |    |- ArgumentError
>     |    |    |- Gem::Requirement::BadRequirementError
>     |    |    |- IO::Buffer::MaskError
>     |    |    `- UncaughtThrowError
>     |    |- EncodingError
>     |    |    |- Encoding::CompatibilityError
>     |    |    |- Encoding::ConverterNotFoundError
>     |    |    |- Encoding::InvalidByteSequenceError
>     |    |    `- Encoding::UndefinedConversionError
>     |    |- FiberError
>     |    |- Fiddle::Error
>     |    |    |- Fiddle::ClearedReferenceError
>     |    |    `- Fiddle::DLError
>     |    |- Gem::Molinillo::ResolverError
>     |    |    |- Gem::Molinillo::CircularDependencyError
>     |    |    |- Gem::Molinillo::NoSuchDependencyError
>     |    |    `- Gem::Molinillo::VersionConflict
>     |    |- Gem::TSort::Cyclic
>     |    |- IOError
>     |    |    |- EOFError
>     |    |    `- IO::TimeoutError
>     |    |- IRB::CantChangeBinding
>     |    |- IRB::CantReturnToNormalMode
>     |    |- IRB::Command::CommandArgumentError
>     |    |- IRB::IllegalParameter
>     |    |- IRB::IrbAlreadyDead
>     |    |- IRB::IrbSwitchedToCurrentThread
>     |    |- IRB::NoSuchJob
>     |    |- IRB::RubyLex::TerminateLineInput
>     |    |- IRB::SourceFinder::EvaluationError
>     |    |- IRB::UndefinedPromptMode
>     |    |- IRB::UnrecognizedSwitch
>     |    |- IndexError
>     |    |    |- KeyError
>     |    |    `- StopIteration
>     |    |         |- ClosedQueueError
>     |    |         `- Ractor::ClosedError
>     |    |- JSON::JSONError
>     |    |    |- JSON::GeneratorError
>     |    |    |- JSON::MissingUnicodeSupport
>     |    |    `- JSON::ParserError
>     |    |         `- JSON::NestingError
>     |    |              `- JSON::CircularDatastructure
>     |    |- LocalJumpError
>     |    |- Math::DomainError
>     |    |- NameError
>     |    |    `- NoMethodError
>     |    |- NoMatchingPatternError
>     |    |    `- NoMatchingPatternKeyError
>     |    |- RangeError
>     |    |    `- FloatDomainError
>     |    |- RegexpError
>     |    |    `- Regexp::TimeoutError
>     |    |- Reline::ConfigEncodingConversionError
>     |    |- Reline::Terminfo::TerminfoError
>     |    |- Ripper::TokenPattern::Error
>     |    |    |- Ripper::TokenPattern::CompileError
>     |    |    `- Ripper::TokenPattern::MatchError
>     |    |- RuntimeError
>     |    |    |- FrozenError
>     |    |    |- Gem::Exception
>     |    |    |    |- Gem::CommandLineError
>     |    |    |    |- Gem::DependencyError
>     |    |    |    |    |- Gem::DependencyResolutionError
>     |    |    |    |    `- Gem::UnsatisfiableDependencyError
>     |    |    |    |- Gem::DependencyRemovalException
>     |    |    |    |- Gem::DocumentError
>     |    |    |    |- Gem::EndOfYAMLException
>     |    |    |    |- Gem::FilePermissionError
>     |    |    |    |- Gem::FormatException
>     |    |    |    |- Gem::GemNotFoundException
>     |    |    |    |    `- Gem::SpecificGemNotFoundException
>     |    |    |    |- Gem::GemNotInHomeException
>     |    |    |    |- Gem::ImpossibleDependenciesError
>     |    |    |    |- Gem::InstallError
>     |    |    |    |    `- Gem::RuntimeRequirementNotMetError
>     |    |    |    |- Gem::InvalidSpecificationException
>     |    |    |    |- Gem::OperationNotSupportedError
>     |    |    |    |- Gem::RemoteError
>     |    |    |    |- Gem::RemoteInstallationCancelled
>     |    |    |    |- Gem::RemoteInstallationSkipped
>     |    |    |    |- Gem::RemoteSourceException
>     |    |    |    |- Gem::RequestSet::Lockfile::ParseError
>     |    |    |    |- Gem::RubyVersionMismatch
>     |    |    |    |- Gem::UninstallError
>     |    |    |    |- Gem::UnknownCommandError
>     |    |    |    |- Gem::VerificationError
>     |    |    |    `- Gem::WebauthnVerificationError
>     |    |    |- IO::Buffer::AccessError
>     |    |    |- IO::Buffer::AllocationError
>     |    |    |- IO::Buffer::InvalidatedError
>     |    |    |- IO::Buffer::LockedError
>     |    |    |- RDoc::Error
>     |    |    |- Ractor::Error
>     |    |    |    |- Ractor::IsolationError
>     |    |    |    |- Ractor::MovedError
>     |    |    |    |- Ractor::RemoteError
>     |    |    |    `- Ractor::UnsafeError
>     |    |    `- Reline::Config::InvalidInputrc
>     |    |- SystemCallError
>     |    |    |- Errno::E2BIG
>     |    |    |- Errno::EACCES
>     |    |    |- Errno::EADDRINUSE
>     |    |    |- Errno::EADDRNOTAVAIL
>     |    |    |- Errno::EAFNOSUPPORT
>     |    |    |- Errno::EAGAIN
>     |    |    |    |- IO::EAGAINWaitReadable
>     |    |    |    `- IO::EAGAINWaitWritable
>     |    |    |- Errno::EALREADY
>     |    |    |- Errno::EAUTH
>     |    |    |- Errno::EBADARCH
>     |    |    |- Errno::EBADEXEC
>     |    |    |- Errno::EBADF
>     |    |    |- Errno::EBADMACHO
>     |    |    |- Errno::EBADMSG
>     |    |    |- Errno::EBADRPC
>     |    |    |- Errno::EBUSY
>     |    |    |- Errno::ECANCELED
>     |    |    |- Errno::ECHILD
>     |    |    |- Errno::ECONNABORTED
>     |    |    |- Errno::ECONNREFUSED
>     |    |    |- Errno::ECONNRESET
>     |    |    |- Errno::EDEADLK
>     |    |    |- Errno::EDESTADDRREQ
>     |    |    |- Errno::EDEVERR
>     |    |    |- Errno::EDOM
>     |    |    |- Errno::EDQUOT
>     |    |    |- Errno::EEXIST
>     |    |    |- Errno::EFAULT
>     |    |    |- Errno::EFBIG
>     |    |    |- Errno::EFTYPE
>     |    |    |- Errno::EHOSTDOWN
>     |    |    |- Errno::EHOSTUNREACH
>     |    |    |- Errno::EIDRM
>     |    |    |- Errno::EILSEQ
>     |    |    |- Errno::EINPROGRESS
>     |    |    |    |- IO::EINPROGRESSWaitReadable
>     |    |    |    `- IO::EINPROGRESSWaitWritable
>     |    |    |- Errno::EINTR
>     |    |    |- Errno::EINVAL
>     |    |    |- Errno::EIO
>     |    |    |- Errno::EISCONN
>     |    |    |- Errno::EISDIR
>     |    |    |- Errno::ELAST
>     |    |    |- Errno::ELOOP
>     |    |    |- Errno::EMFILE
>     |    |    |- Errno::EMLINK
>     |    |    |- Errno::EMSGSIZE
>     |    |    |- Errno::EMULTIHOP
>     |    |    |- Errno::ENAMETOOLONG
>     |    |    |- Errno::ENEEDAUTH
>     |    |    |- Errno::ENETDOWN
>     |    |    |- Errno::ENETRESET
>     |    |    |- Errno::ENETUNREACH
>     |    |    |- Errno::ENFILE
>     |    |    |- Errno::ENOATTR
>     |    |    |- Errno::ENOBUFS
>     |    |    |- Errno::ENODATA
>     |    |    |- Errno::ENODEV
>     |    |    |- Errno::ENOENT
>     |    |    |- Errno::ENOEXEC
>     |    |    |- Errno::ENOLCK
>     |    |    |- Errno::ENOLINK
>     |    |    |- Errno::ENOMEM
>     |    |    |- Errno::ENOMSG
>     |    |    |- Errno::ENOPOLICY
>     |    |    |- Errno::ENOPROTOOPT
>     |    |    |- Errno::ENOSPC
>     |    |    |- Errno::ENOSR
>     |    |    |- Errno::ENOSTR
>     |    |    |- Errno::ENOSYS
>     |    |    |- Errno::ENOTBLK
>     |    |    |- Errno::ENOTCONN
>     |    |    |- Errno::ENOTDIR
>     |    |    |- Errno::ENOTEMPTY
>     |    |    |- Errno::ENOTRECOVERABLE
>     |    |    |- Errno::ENOTSOCK
>     |    |    |- Errno::ENOTSUP
>     |    |    |- Errno::ENOTTY
>     |    |    |- Errno::ENXIO
>     |    |    |- Errno::EOPNOTSUPP
>     |    |    |- Errno::EOVERFLOW
>     |    |    |- Errno::EOWNERDEAD
>     |    |    |- Errno::EPERM
>     |    |    |- Errno::EPFNOSUPPORT
>     |    |    |- Errno::EPIPE
>     |    |    |- Errno::EPROCLIM
>     |    |    |- Errno::EPROCUNAVAIL
>     |    |    |- Errno::EPROGMISMATCH
>     |    |    |- Errno::EPROGUNAVAIL
>     |    |    |- Errno::EPROTO
>     |    |    |- Errno::EPROTONOSUPPORT
>     |    |    |- Errno::EPROTOTYPE
>     |    |    |- Errno::EPWROFF
>     |    |    |- Errno::ERANGE
>     |    |    |- Errno::EREMOTE
>     |    |    |- Errno::EROFS
>     |    |    |- Errno::ERPCMISMATCH
>     |    |    |- Errno::ESHLIBVERS
>     |    |    |- Errno::ESHUTDOWN
>     |    |    |- Errno::ESOCKTNOSUPPORT
>     |    |    |- Errno::ESPIPE
>     |    |    |- Errno::ESRCH
>     |    |    |- Errno::ESTALE
>     |    |    |- Errno::ETIME
>     |    |    |- Errno::ETIMEDOUT
>     |    |    |- Errno::ETOOMANYREFS
>     |    |    |- Errno::ETXTBSY
>     |    |    |- Errno::EUSERS
>     |    |    |- Errno::EXDEV
>     |    |    `- Errno::NOERROR
>     |    |- ThreadError
>     |    |- TypeError
>     |    `- ZeroDivisionError
>     |- SystemExit
>     |    `- Gem::SystemExitException
>     |- SystemStackError
>     `- fatal
>
> -a
>
> On Tue, Oct 29, 2024 at 8:48 AM Rodrigo Rosenfeld Rosas via ruby-core <
> ruby-core@ml.ruby-lang.org> wrote:
>
>> Hello, I couldn't find any documentation about the subject, so I thought
>> this behavior should be probably documented.
>>
>> Given the following code:
>>
>> def raise_error
>>   raise "runtime error message"
>> rescue => e
>>   "StandardError: #{e.message}"
>> rescue RuntimeError => e
>>   puts "RuntimeError raised: #{e.message}"
>>   raise StandardError, "standard error message"
>> end
>>
>> # same, but the order of the rescue blocks are inverted
>> def raise_error2
>>   raise "runtime error message"
>> rescue RuntimeError => e
>>   puts "RuntimeError raised: #{e.message}"
>>   raise StandardError, "standard error message"
>> rescue => e
>>   "StandardError: #{e.message}"
>> end
>>
>> p ["raise_error", raise_error ]
>>
>> begin
>>   p ["raise_error2", raise_error2]
>> rescue => e
>>   puts "raise_error2 raised: #{e.message}"
>> end
>>
>> When we run it, this is the output in Ruby 3.3.5:
>>
>> ["raise_error", "StandardError: runtime error message"]
>>
>> RuntimeError raised: runtime error message
>>
>> raise_error2 raised: standard error message
>>
>>
>> In the first case (raise_error), the code raised from the RuntimeError
>> rescue block is rescued by the StandardError block, but when inverting the
>> order of the rescue blocks (raise_error2) then this won't happen.
>>
>> Is this part of the specs? Is this behavior documented somewhere? Could
>> this behavior differ in different Ruby implementations and versions? Or can
>> we rely on such behavior?
>>
>>
>> This chapter doesn't include such case in its examples:
>>
>> https://ruby-doc.com/docs/ProgrammingRuby/html/tut_exceptions.html
>>
>> Or this documentation about Exceptions:
>>
>> https://ruby-doc.org/3.3.5/syntax/exceptions_rdoc.html
>>
>> Is there a recommended way for wrapping exceptions into a particular one
>> and then handling that exception from within the same method rescue blocks?
>> Or is this considered a bad practice?
>>
>>
>>  ______________________________________________
>>  ruby-core mailing list -- ruby-core@ml.ruby-lang.org
>>  To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
>>  ruby-core info --
>> https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/
>
>
>
> --
> Austin Ziegler • halostatue@gmail.com • austin@halostatue.ca
> http://www.halostatue.ca/http://twitter.com/halostatue
>

[-- Attachment #1.2: Type: text/html, Size: 18426 bytes --]

[-- Attachment #2: Type: text/plain, Size: 254 bytes --]

 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/

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

end of thread, other threads:[~2024-10-29 19:24 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-10-29 12:42 [ruby-core:119637] Behavior of raising from rescue blocks when multiple rescue blocks exist Rodrigo Rosenfeld Rosas via ruby-core
2024-10-29 18:07 ` [ruby-core:119639] " Austin Ziegler via ruby-core
2024-10-29 19:22   ` [ruby-core:119640] " Rodrigo Rosenfeld Rosas via ruby-core

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 NNTP newsgroup(s).