fix NameError message

The following code produces two NameErrors respectively
and they are independent, but the second one can show
`private constant` message because of first NameError.

```ruby
class C
  class PrivateClass; end
  private_constant :PrivateClass
end

begin
  eval('class C::PrivateClass; end')
rescue => e
  p e
end

begin
  Object.const_get 'Foo'
rescue => e
  p e
end

  #<NameError: private constant C::PrivateClass referenced>
  #<NameError: private constant C::Foo referenced>
  #=> should be #<NameError: uninitialized constant Foo>
```

It fails the test-all tests with
`make test-all TESTS='ruby/class ruby/parse --seed=58891 -v`.

The reason is clear miss from https://github.com/ruby/ruby/commit/7387c08373a
This commit is contained in:
Koichi Sasada 2023-04-19 11:40:16 +09:00
parent 62781d479b
commit 628e432739
Notes: git 2023-04-19 05:54:16 +00:00
2 changed files with 15 additions and 3 deletions

View File

@ -355,6 +355,17 @@ class TestClass < Test::Unit::TestCase
assert_equal(42, PrivateClass.new.foo)
end
def test_private_const_access
assert_raise_with_message NameError, /uninitialized/ do
begin
eval('class ::TestClass::PrivateClass; end')
rescue NameError => e
end
Object.const_get "NOT_AVAILABLE_CONST_NAME_#{__LINE__}"
end
end
StrClone = String.clone
Class.new(StrClone)

View File

@ -2073,11 +2073,12 @@ rb_const_missing(VALUE klass, VALUE name)
VALUE
rb_mod_const_missing(VALUE klass, VALUE name)
{
VALUE ref = GET_EC()->private_const_reference;
rb_execution_context_t *ec = GET_EC();
VALUE ref = ec->private_const_reference;
rb_vm_pop_cfunc_frame();
if (ref) {
rb_name_err_raise("private constant %2$s::%1$s referenced",
ref, name);
ec->private_const_reference = 0;
rb_name_err_raise("private constant %2$s::%1$s referenced", ref, name);
}
uninitialized_constant(klass, name);