Ruby 4.0.0 Lançado

Escrito por naruse em 25/12/2025
Traduzido por guicruzzs

Estamos felizes em anunciar o lançamento do Ruby 4.0.0. Ruby 4.0 introduz o “Ruby Box” e o “ZJIT”, além de muitas melhorias.

Ruby Box

Ruby Box é um novo recurso (experimental) para fornecer separação de definições. Ruby Box é habilitado quando a variável de ambiente RUBY_BOX=1 é especificada. A classe é Ruby::Box.

Definições carregadas em uma box são isoladas dentro dela. Ruby Box pode isolar/separar monkey patches, alterações em variáveis globais/de classe, definições de classes/módulos e bibliotecas nativas/Ruby carregadas de outras boxes.

Casos de uso esperados incluem:

  • Executar casos de teste em uma box para proteger outros testes quando o caso de teste usa monkey patches para sobrescrever algo
  • Executar boxes de aplicações web em paralelo para fazer blue‑green deployment em um servidor de aplicação dentro de um processo Ruby
  • Executar boxes de aplicações web em paralelo para avaliar atualizações de dependências por um certo período de tempo, verificando o diff da resposta usando código Ruby
  • Ser usada como a API de base (baixo nível) para implementar algum tipo de API de “pacotes” (alto nível) (ainda não foi projetada)

Para mais detalhes sobre o “Ruby Box”, consulte Ruby::Box. [Feature #21311] [Misc #21385]

ZJIT

ZJIT é um novo compilador just‑in‑time (JIT), desenvolvido como a próxima geração do YJIT. Você precisa do Rust 1.85.0 ou mais recente para construir o Ruby com suporte ao ZJIT, e o ZJIT é habilitado quando --zjit é especificado.

Estamos construindo um novo compilador para Ruby porque queremos tanto elevar o teto de desempenho (unidade de compilação maior e IR em SSA) quanto incentivar mais contribuições externas (tornando‑se um compilador de métodos mais tradicional). Veja nosso post no blog para mais detalhes.

ZJIT é mais rápido que o interpretador, mas ainda não é tão rápido quanto o YJIT. Incentivamos você a experimentar o ZJIT, mas talvez seja melhor adiar o uso em produção por enquanto. Fique de olho no ZJIT do Ruby 4.1.

Melhorias em Ractor

Ractor, o mecanismo de execução paralela do Ruby, recebeu várias melhorias. Uma nova classe, Ractor::Port, foi introduzida para resolver problemas relacionados ao envio e recebimento de mensagens (veja este post no blog). Além disso, Ractor.shareable_proc facilita compartilhar objetos Proc entre Ractors.

Do ponto de vista de desempenho, muitas estruturas de dados internas foram melhoradas para reduzir significativamente a contenção em um lock global, liberando mais paralelismo. Ractors também agora compartilham menos dados internos, resultando em menos contenção de cache de CPU quando executados em paralelo.

Ractor foi introduzido pela primeira vez no Ruby 3.0 como um recurso experimental. Nosso objetivo é remover o status de “experimental” no próximo ano.

Mudanças na linguagem

  • *nil não chama mais nil.to_a, de forma semelhante a como **nil não chama nil.to_hash. [Feature #21047]

  • Operadores lógicos binários (||, &&, and e or) no início de uma linha continuam a linha anterior, assim como o encadeamento por ponto. Os exemplos de código a seguir são equivalentes:

      if condition1
         && condition2
        ...
      end
    

    Anteriormente:

      if condition1 && condition2
        ...
      end
    
      if condition1 &&
         condition2
        ...
      end
    

    [Feature #20925]

Atualizações de classes principais

Nota: Estamos listando apenas atualizações notáveis das classes principais.

  • Array

    • Array#rfind foi adicionado como uma alternativa mais eficiente a array.reverse_each.find. [Feature #21678]
    • Array#find foi adicionado como uma sobrescrita mais eficiente de Enumerable#find. [Feature #21678]
  • Binding

    • Binding#local_variables não inclui mais parâmetros numerados. Além disso, Binding#local_variable_get, Binding#local_variable_set e Binding#local_variable_defined? deixam de lidar com parâmetros numerados. [Bug #21049]

    • Binding#implicit_parameters, Binding#implicit_parameter_get e Binding#implicit_parameter_defined? foram adicionados para acessar parâmetros numerados e o parâmetro it. [Bug #21049]

  • Enumerator

    • Enumerator.produce agora aceita um argumento de palavra‑chave opcional size para especificar o tamanho do enumerador. Pode ser um inteiro, Float::INFINITY, um objeto chamável (como uma lambda) ou nil para indicar tamanho desconhecido. Quando não especificado, o tamanho padrão é Float::INFINITY.

        # Enumerador infinito
        enum = Enumerator.produce(1, size: Float::INFINITY, &:succ)
        enum.size  # => Float::INFINITY
      
        # Enumerador finito com tamanho conhecido/computável
        abs_dir = File.expand_path("./baz") # => "/foo/bar/baz"
        traverser = Enumerator.produce(abs_dir, size: -> { abs_dir.count("/") + 1 }) {
          raise StopIteration if it == "/"
          File.dirname(it)
        }
        traverser.size  # => 4
      

      [Feature #21701]

  • ErrorHighlight

    • Quando um ArgumentError é levantado, agora são exibidos trechos de código tanto da chamada de método (caller) quanto da definição de método (callee). [Feature #21543]

      test.rb:1:in 'Object#add': wrong number of arguments (given 1, expected 2) (ArgumentError)
      
          caller: test.rb:3
          | add(1)
            ^^^
          callee: test.rb:1
          | def add(x, y) = x + y
                ^^^
              from test.rb:3:in '<main>'
      
  • Fiber

    • Suporte ao argumento Fiber#raise(cause:) foi introduzido, semelhante a Kernel#raise. [Feature #21360]
  • Fiber::Scheduler

    • Introduz Fiber::Scheduler#fiber_interrupt para interromper um fiber com uma exceção específica. O caso de uso inicial é interromper um fiber que está aguardando uma operação de IO bloqueante quando essa operação é encerrada. [Feature #21166]

    • Introduz Fiber::Scheduler#yield para permitir que o escalonador de fibers continue processando quando exceções de sinal estão desabilitadas. [Bug #21633]

    • Reintroduz o hook Fiber::Scheduler#io_close para IO#close assíncrono.

    • Invoca Fiber::Scheduler#io_write ao esvaziar o buffer de escrita de IO. [Bug #21789]

  • File

    • File::Stat#birthtime agora está disponível no Linux via a chamada de sistema statx, quando suportada pelo kernel e pelo sistema de arquivos. [Feature #21205]
  • IO

    • IO.select aceita Float::INFINITY como argumento de timeout. [Feature #20610]

    • Um comportamento obsoleto, criação de processos por métodos da classe IO com um | inicial, foi removido. [Feature #19630]

  • Kernel

    • Kernel#inspect agora verifica a existência de um método #instance_variables_to_inspect, permitindo controlar quais variáveis de instância são exibidas na string de #inspect:

        class DatabaseConfig
          def initialize(host, user, password)
            @host = host
            @user = user
            @password = password
          end
      
          private def instance_variables_to_inspect = [:@host, :@user]
        end
      
        conf = DatabaseConfig.new("localhost", "root", "hunter2")
        conf.inspect #=> #<DatabaseConfig:0x0000000104def350 @host="localhost", @user="root">
      

      [Feature #21219]

    • Um comportamento obsoleto, criação de processos por Kernel#open com um | inicial, foi removido. [Feature #19630]

  • Math

  • Pathname

    • Pathname foi promovida de gem padrão para classe principal do Ruby. [Feature #17473]
  • Proc

    • Proc#parameters agora mostra parâmetros opcionais anônimos como [:opt] em vez de [:opt, nil], tornando a saída consistente com o caso em que o parâmetro anônimo é obrigatório. [Bug #20974]
  • Ractor

    • A classe Ractor::Port foi adicionada como um novo mecanismo de sincronização para comunicação entre Ractors. [Feature #21262]

        port1 = Ractor::Port.new
        port2 = Ractor::Port.new
        Ractor.new port1, port2 do |port1, port2|
          port1 << 1
          port2 << 11
          port1 << 2
          port2 << 12
        end
        2.times{ p port1.receive } #=> 1, 2
        2.times{ p port2.receive } #=> 11, 12
      

      Ractor::Port fornece os seguintes métodos:

      • Ractor::Port#receive
      • Ractor::Port#send (ou Ractor::Port#<<)
      • Ractor::Port#close
      • Ractor::Port#closed?

      Como resultado, Ractor.yield e Ractor#take foram removidos.

    • Ractor#join e Ractor#value foram adicionados para aguardar o término de um Ractor. São semelhantes a Thread#join e Thread#value.

    • Ractor#monitor e Ractor#unmonitor foram adicionados como interfaces de baixo nível usadas internamente para implementar Ractor#join.

    • Ractor.select agora aceita apenas Ractors e Ports. Se Ractors forem fornecidos, retorna quando um Ractor termina.

    • Ractor#default_port foi adicionado. Cada Ractor possui uma porta padrão, usada por Ractor.send e Ractor.receive.

    • Ractor#close_incoming e Ractor#close_outgoing foram removidos.

    • Ractor.shareable_proc e Ractor.shareable_lambda foram introduzidos para criar Proc ou lambda compartilháveis. [Feature #21550], [Feature #21557]

  • Range

    • Range#to_set agora realiza verificações de tamanho para evitar problemas com ranges infinitos. [Bug #21654]

    • Range#overlap? agora lida corretamente com ranges infinitos (sem limites). [Bug #21185]

    • O comportamento de Range#max em ranges inteiros sem início foi corrigido. [Bug #21174] [Bug #21175]

  • Ruby

    • Um novo módulo de nível superior Ruby foi definido, contendo constantes relacionadas ao Ruby. Este módulo foi reservado no Ruby 3.4 e agora é oficialmente definido. [Feature #20884]
  • Ruby::Box

  • Set

    • Set agora é uma classe principal, em vez de uma classe da biblioteca padrão carregada sob demanda. [Feature #21216]

    • Set#inspect agora usa uma forma de exibição mais simples, semelhante a arrays literais (por exemplo, Set[1, 2, 3] em vez de #<Set: {1, 2, 3}>). [Feature #21389]

    • Passar argumentos para Set#to_set e Enumerable#to_set agora é desencorajado (deprecated). [Feature #21390]

  • Socket

    • Socket.tcp e TCPSocket.new aceitam um argumento de palavra‑chave open_timeout para especificar o timeout da conexão inicial. [Feature #21347]

    • Quando um timeout especificado pelo usuário ocorria em TCPSocket.new, anteriormente podiam ser levantadas Errno::ETIMEDOUT ou IO::TimeoutError, dependendo da situação. Esse comportamento foi unificado para que agora IO::TimeoutError seja sempre levantado. (Observe que, em Socket.tcp, ainda podem existir casos em que Errno::ETIMEDOUT seja levantada em situações semelhantes, e que, em ambos os casos, Errno::ETIMEDOUT pode ser levantada quando o timeout ocorre no nível do sistema operacional.)

  • String

    • Atualização do Unicode para a versão 17.0.0 e do Emoji para a versão 17.0. [Feature #19908][Feature #20724][Feature #21275] (também se aplica a Regexp)

    • String#strip, strip!, lstrip, lstrip!, rstrip e rstrip! foram estendidos para aceitar argumentos *selectors. [Feature #21552]

  • Thread

    • Suporte ao argumento Thread#raise(cause:) foi introduzido, semelhante a Kernel#raise. [Feature #21360]

Atualizações da Biblioteca Padrão

Listamos aqui apenas mudanças na biblioteca padrão que são alterações de recurso notáveis.

Outras mudanças estão listadas nas seções seguintes. Também listamos o histórico de lançamentos desde a versão anterior empacotada, Ruby 3.4.0, quando há releases no GitHub.

As seguintes gems empacotadas foram promovidas de gems padrão:

As seguintes gems padrão foram adicionadas:

  • win32-registry 0.1.2

As seguintes gems padrão foram atualizadas:

As seguintes gems empacotadas foram atualizadas:

RubyGems e Bundler

Ruby 4.0 empacota RubyGems e Bundler versão 4. Veja os links a seguir para mais detalhes.

Plataformas suportadas

  • Windows

    • Suporte a versões do MSVC anteriores a 14.0 (_MSC_VER 1900) foi removido. Isso significa que o Visual Studio 2015 ou mais recente agora é obrigatório.

Problemas de compatibilidade

  • Os seguintes métodos foram removidos de Ractor devido à adição de Ractor::Port:

    • Ractor.yield
    • Ractor#take
    • Ractor#close_incoming
    • Ractor#close_outgoing

    [Feature #21262]

  • ObjectSpace._id2ref está obsoleto. [Feature #15408]

  • Process::Status#& e Process::Status#>> foram removidos. Eles foram marcados como obsoletos no Ruby 3.3. [Bug #19868]

  • rb_path_check foi removida. Essa função era usada para verificação de caminhos com $SAFE, que foi removida no Ruby 2.7, e já estava obsoleta. [Feature #20971]

  • Um backtrace para ArgumentError de “wrong number of arguments” agora inclui o nome da classe ou módulo do receiver (por exemplo, em Foo#bar em vez de apenas bar). [Bug #21698]

  • Backtraces não exibem mais frames internal. Esses métodos agora aparecem como se estivessem no arquivo de código Ruby, consistente com outros métodos implementados em C. [Bug #20968]

    Antes:

    ruby -e '[1].fetch_values(42)'
    <internal:array>:211:in 'Array#fetch': index 42 outside of array bounds: -1...1 (IndexError)
            from <internal:array>:211:in 'block in Array#fetch_values'
            from <internal:array>:211:in 'Array#map!'
            from <internal:array>:211:in 'Array#fetch_values'
            from -e:1:in '<main>'
    

    Depois:

    $ ruby -e '[1].fetch_values(42)'
    -e:1:in 'Array#fetch_values': index 42 outside of array bounds: -1...1 (IndexError)
            from -e:1:in '<main>'
    

Problemas de compatibilidade da biblioteca padrão

  • A biblioteca CGI foi removida das gems padrão. Agora fornecemos apenas cgi/escape para os seguintes métodos:

    • CGI.escape e CGI.unescape
    • CGI.escapeHTML e CGI.unescapeHTML
    • CGI.escapeURIComponent e CGI.unescapeURIComponent
    • CGI.escapeElement e CGI.unescapeElement

    [Feature #21258]

  • Com a mudança de Set da biblioteca padrão para classe principal, set/sorted_set.rb foi removido e SortedSet não é mais uma constante carregada sob demanda. Por favor, instale a gem sorted_set e faça require 'sorted_set' para usar SortedSet. [Feature #21287]

  • Net::HTTP

    • O comportamento padrão de configurar automaticamente o cabeçalho Content-Type como application/x-www-form-urlencoded para requisições com corpo (por exemplo, POST, PUT) quando o cabeçalho não era definido explicitamente foi removido. Se sua aplicação dependia desse padrão automático, agora as requisições serão enviadas sem um cabeçalho Content-Type, o que pode quebrar compatibilidade com alguns servidores. [GH-net-http #205]

Atualizações da C API

  • IO

    • rb_thread_fd_close está obsoleta e agora é um no‑op. Se você precisar expor descritores de arquivo de extensões C para código Ruby, crie uma instância de IO usando RUBY_IO_MODE_EXTERNAL e use rb_io_close(io) para fechá‑la (isso também interrompe e aguarda todas as operações pendentes na instância de IO). Fechar descritores de arquivo diretamente não interrompe operações pendentes e pode levar a comportamento indefinido. Em outras palavras, se dois objetos IO compartilham o mesmo descritor de arquivo, fechar um não afeta o outro. [Feature #18455]
  • GVL

    • rb_thread_call_with_gvl agora funciona com ou sem o GVL. Isso permite que gems evitem verificar ruby_thread_has_gvl_p. Ainda assim, é importante ser cuidadoso com o GVL. [Feature #20750]
  • Set

    • Uma API em C para Set foi adicionada. Os seguintes métodos são suportados: [Feature #21459]

      • rb_set_foreach
      • rb_set_new
      • rb_set_new_capa
      • rb_set_lookup
      • rb_set_add
      • rb_set_clear
      • rb_set_delete
      • rb_set_size

Melhorias na implementação

  • Class#new (por exemplo, Object.new) está mais rápido em todos os casos, mas especialmente ao passar argumentos de palavra‑chave. Isso também foi integrado ao YJIT e ao ZJIT. [Feature #21254]
  • Heaps do GC de pools de tamanhos diferentes agora crescem de forma independente, reduzindo o uso de memória quando apenas alguns pools contêm objetos de vida longa.
  • A varredura (sweeping) do GC está mais rápida em páginas de objetos grandes.
  • Objetos de “generic ivar” (String, Array, TypedData, etc.) agora usam um novo objeto interno de “fields” para acesso mais rápido a variáveis de instância.
  • O GC evita manter uma tabela interna id2ref até que seja usada pela primeira vez, tornando a alocação de object_id e a varredura do GC mais rápidas.
  • object_id e hash estão mais rápidos em objetos Class e Module.
  • Inteiros bignum maiores agora podem permanecer embutidos usando alocação de largura variável.
  • Random, Enumerator::Product, Enumerator::Chain, Addrinfo, StringScanner e alguns objetos internos agora são protegidos por write‑barrier, o que reduz a sobrecarga do GC.

Ractor

Muito trabalho foi feito para tornar Ractors mais estáveis, performáticos e utilizáveis. Essas melhorias aproximam a implementação de Ractor de deixar o status experimental.

  • Melhorias de desempenho
    • Strings congeladas e a tabela de símbolos usam internamente um hash set lock‑free. [Feature #21268]
    • A busca no cache de métodos evita bloqueios na maioria dos casos.
    • O acesso a variáveis de instância de classes (e generic ivar) está mais rápido e evita bloqueios.
    • A contenção de cache de CPU é evitada na alocação de objetos usando um contador por Ractor.
    • A contenção de cache de CPU é evitada em xmalloc/xfree usando um contador local à thread.
    • object_id evita bloqueios na maioria dos casos.
  • Correções de bugs e estabilidade
    • Correções de deadlocks potenciais ao combinar Ractors e Threads.
    • Correções em problemas com require e autoload em Ractor.
    • Correções em problemas de codificação/transcodificação entre Ractors.
    • Correções em condições de corrida em operações do GC e invalidação de métodos.
    • Correções em problemas com processos que fazem fork após iniciar um Ractor.
    • Contagens de alocação do GC agora são precisas sob Ractors.
    • Correção de TracePoints que não funcionavam após o GC. [Bug #19112]

JIT

  • ZJIT
    • Introduz um compilador JIT baseado em métodos experimental. Onde disponível, o ZJIT pode ser habilitado em tempo de execução com a opção --zjit ou chamando RubyVM::ZJIT.enable. Ao compilar o Ruby, é necessário Rust 1.85.0 ou mais recente para incluir suporte ao ZJIT.
    • A partir do Ruby 4.0.0, o ZJIT é mais rápido que o interpretador, mas ainda não é tão rápido quanto o YJIT. Incentivamos a experimentação com o ZJIT, mas recomendamos não usá‑lo em produção por enquanto.
    • Nosso objetivo é tornar o ZJIT mais rápido que o YJIT e pronto para produção no Ruby 4.1.
  • YJIT
    • RubyVM::YJIT.runtime_stats
      • ratio_in_yjit não funciona mais na build padrão. Use --enable-yjit=stats em configure para habilitá‑lo com --yjit-stats.
      • Adiciona invalidate_everything às estatísticas padrão, que é incrementada quando todo o código é invalidado por TracePoint.
    • Adiciona opções mem_size: e call_threshold: a RubyVM::YJIT.enable.
  • RJIT
    • --rjit foi removido. A implementação da API de JIT de terceiros será movida para o repositório ruby/rjit.

Veja NEWS ou logs de commits para mais detalhes.

Com essas mudanças, 3889 arquivos alterados, 230769 inserções(+), 297003 deleções(-) desde Ruby 3.4.0!

Feliz Natal, um Próspero Ano Novo e aproveite a programação com Ruby 4.0!

Download

  • https://cache.ruby-lang.org/pub/ruby/4.0/ruby-4.0.0.tar.gz

    TAMANHO: 23955109
    SHA1: 754e39e9ad122e1b6deaed860350bac133a35ed3
    SHA256: 2e8389c8c072cb658c93a1372732d9eac84082c88b065750db1e52a5ac630271
    SHA512: 688254e939b197d564e896fb951bc1abf07142f489e91c5ed0b11f68f52d6adb6b1f86616fe03f1f0bb434beeef7e75e158b9c616afb39bb34403b0b78d2ee19
    
  • https://cache.ruby-lang.org/pub/ruby/4.0/ruby-4.0.0.tar.xz

    TAMANHO: 18008368
    SHA1: 05ec670e86f84325c5353ef2f2888e53b6adc602
    SHA256: a72bacee9de07283ebc19baa4ac243b193129f21aa4e168c7186fb1fe7d07fe1
    SHA512: 2d5b2e566eaf70a5f3ea6ce6afc0611c0415de58a41336ef7a0b855c9a91eda9aa790a5f8b48e40a1eb9d50f8ea0f687216e617f16c8d040a08474f3116518a4
    
  • https://cache.ruby-lang.org/pub/ruby/4.0/ruby-4.0.0.zip

    TAMANHO: 29253204
    SHA1: 0b69f89d1d140157251c0d3a6032f6c45cdf81e8
    SHA256: 70cb1bf89279b86ab9a975d504607c051fc05ee03e311d550a5541b65e373455
    SHA512: a72e076ef618c0aeb9d20cf22e6fb12fda36809c0064ef0f98153b95a0bac257ef606342444a38f992c4594bf376a4d264686cf597463aa6f111220798784302
    

O que é Ruby

Ruby foi desenvolvido pela primeira vez por Matz (Yukihiro Matsumoto) em 1993, e agora é desenvolvido como Open Source. Ele roda em várias plataformas e é usado em todo o mundo, especialmente para desenvolvimento web.

Notícias Recentes

Mais Notícias...