Feature #16644

qualified const init (self::CONST1 = 1) should be allowed in methods

Added by bughit (bug hit) 6 months ago. Updated 6 months ago.

Target version:


module Mod1
  def self.define_consts
    const_set(:CONST1, :CONST1)

    # this is actual const re-assignment but only a warning
    const_set(:CONST1, :CONST1)

    # this is const initialization but becomes an error
    # because it looks like it could be re-assignment
    # if actual const re-assignment is only a warning
    # why is a possible const re-assignment (which might not be one), an error
    self::CONST2 = :CONST2 unless const_defined?(:CONST2, false)



Updated by jeremyevans0 (Jeremy Evans) 6 months ago

  • Backport deleted (2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN)
  • ruby -v deleted (ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-linux])
  • Tracker changed from Bug to Misc

These are two different things. Ruby always warns for assigning to an existing constant, regardless of using const_set or CONST = .... It does not support using CONST = ... inside a method, though const_set is allowed. Similarly, you can use and to define classes and modules in method bodies, but you can't use the class or module keywords directly in method bodies.

This behavior exists at least back to 1.8, and probably before that. I'm fairly sure this is the expected behavior. If you would like the behavior changed, please submit a feature request.

I realize this does not directly answer the question in the issue subject. I'm switching this to the Misc tracker, since this is not a bug report.

Updated by bughit (bug hit) 6 months ago

  • Subject changed from why is potential dynamic constant assignment an error when actual dynamic constant assignment is only a warning to qualified const init (self::CONST1 = 1) should be allowed in methods
  • Tracker changed from Misc to Feature

a qualified const init is so similar to meta-programming const_set that there's no reason to block it

module Mod1

  def define_consts(mod)

    # since this allowed
    mod.const_set(:CONST1, :CONST1) unless mod.const_defined?(:CONST1, false)

    # this should be too
    mod::CONST2 = :CONST2 unless mod.const_defined?(:CONST2, false)



Updated by matz (Yukihiro Matsumoto) 6 months ago

Use const_set. I'd rather make all const re-assignment error if compatibility does not matter.



Updated by matz (Yukihiro Matsumoto) 6 months ago

  • Status changed from Open to Rejected

Updated by bughit (bug hit) 6 months ago

I'd rather make all const re-assignment error

I don't disagree, actual const re-assignment, dynamically detected, probably should be an error. But then especially, there is no reason that a qualified const initialization (mod::CONST2 = :CONST2 unless mod.const_defined?(:CONST2, false)) should be an error. You would already be protected from const re-assignment, so why block what is simply a more direct syntax for initializing a const from a macro method?

Updated by Hanmac (Hans Mackowiak) 6 months ago

bughit (bug hit) i think you are looking for #const_missing instead?

Also available in: Atom PDF