ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
From: Rodrigo Rosenfeld Rosas via ruby-core <ruby-core@ml.ruby-lang.org>
To: Austin Ziegler <halostatue@gmail.com>
Cc: Ruby developers <ruby-core@ml.ruby-lang.org>,
	Rodrigo Rosenfeld Rosas <rr.rosas@gmail.com>
Subject: [ruby-core:119640] Re: Behavior of raising from rescue blocks when multiple rescue blocks exist
Date: Tue, 29 Oct 2024 16:22:05 -0300	[thread overview]
Message-ID: <CAGmv+w+1vyj=+wdH7SonuXX7HzpuWETBi-Na7jKWTDz+mPXoBQ@mail.gmail.com> (raw)
In-Reply-To: <CAJ4ekQuDv7xsVH0-UHvmzMB5rFSjXLy5MgWoB5gCcUDBk3jYPQ@mail.gmail.com>


[-- 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/

      reply	other threads:[~2024-10-29 19:24 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-10-29 12:42 [ruby-core:119637] " Rodrigo Rosenfeld Rosas via ruby-core
2024-10-29 18:07 ` [ruby-core:119639] " Austin Ziegler via ruby-core
2024-10-29 19:22   ` Rodrigo Rosenfeld Rosas via ruby-core [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAGmv+w+1vyj=+wdH7SonuXX7HzpuWETBi-Na7jKWTDz+mPXoBQ@mail.gmail.com' \
    --to=ruby-core@ml.ruby-lang.org \
    --cc=halostatue@gmail.com \
    --cc=rr.rosas@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).