summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--constant.h1
-rw-r--r--test/ruby/test_autoload.rb40
-rw-r--r--variable.c49
-rw-r--r--version.h6
-rw-r--r--vm_core.h2
-rw-r--r--vm_insnhelper.c2
6 files changed, 83 insertions, 17 deletions
diff --git a/constant.h b/constant.h
index 76b59fa047..fcccf07384 100644
--- a/constant.h
+++ b/constant.h
@@ -46,5 +46,6 @@ int rb_public_const_defined(VALUE klass, ID id);
int rb_public_const_defined_at(VALUE klass, ID id);
int rb_public_const_defined_from(VALUE klass, ID id);
rb_const_entry_t *rb_const_lookup(VALUE klass, ID id);
+int rb_autoloading_value(VALUE mod, ID id, VALUE *value, rb_const_flag_t *flag);
#endif /* CONSTANT_H */
diff --git a/test/ruby/test_autoload.rb b/test/ruby/test_autoload.rb
index 9d16a45e23..0220f3e27d 100644
--- a/test/ruby/test_autoload.rb
+++ b/test/ruby/test_autoload.rb
@@ -245,6 +245,46 @@ p Foo::Bar
assert_ruby_status([script], '', '[ruby-core:81016] [Bug #13526]')
end
+ def test_autoload_private_constant
+ Dir.mktmpdir('autoload') do |tmpdir|
+ File.write(tmpdir+"/zzz.rb", "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ class AutoloadTest
+ ZZZ = :ZZZ
+ private_constant :ZZZ
+ end
+ end;
+ assert_separately(%W[-I #{tmpdir}], "#{<<-"begin;"}\n#{<<-'end;'}")
+ bug = '[ruby-core:85516] [Bug #14469]'
+ begin;
+ class AutoloadTest
+ autoload :ZZZ, "zzz.rb"
+ end
+ assert_raise(NameError, bug) {AutoloadTest::ZZZ}
+ end;
+ end
+ end
+
+ def test_autoload_deprecate_constant
+ Dir.mktmpdir('autoload') do |tmpdir|
+ File.write(tmpdir+"/zzz.rb", "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ class AutoloadTest
+ ZZZ = :ZZZ
+ deprecate_constant :ZZZ
+ end
+ end;
+ assert_separately(%W[-I #{tmpdir}], "#{<<-"begin;"}\n#{<<-'end;'}")
+ bug = '[ruby-core:85516] [Bug #14469]'
+ begin;
+ class AutoloadTest
+ autoload :ZZZ, "zzz.rb"
+ end
+ assert_warning(/ZZZ is deprecated/, bug) {AutoloadTest::ZZZ}
+ end;
+ end
+ end
+
def add_autoload(path)
(@autoload_paths ||= []) << path
::Object.class_eval {autoload(:AutoloadTest, path)}
diff --git a/variable.c b/variable.c
index 52ea6b4cab..53ad84f214 100644
--- a/variable.c
+++ b/variable.c
@@ -1856,6 +1856,7 @@ struct autoload_state {
struct autoload_data_i {
VALUE feature;
int safe_level;
+ rb_const_flag_t flag;
VALUE value;
struct autoload_state *state; /* points to on-stack struct */
};
@@ -1938,6 +1939,7 @@ rb_autoload_str(VALUE mod, ID id, VALUE file)
ele->safe_level = rb_safe_level();
ele->value = Qundef;
ele->state = 0;
+ ele->flag = CONST_PUBLIC;
st_insert(tbl, (st_data_t)id, (st_data_t)ad);
}
@@ -2013,7 +2015,7 @@ check_autoload_required(VALUE mod, ID id, const char **loadingpath)
}
int
-rb_autoloading_value(VALUE mod, ID id, VALUE* value)
+rb_autoloading_value(VALUE mod, ID id, VALUE* value, rb_const_flag_t *flag)
{
VALUE load;
struct autoload_data_i *ele;
@@ -2026,6 +2028,9 @@ rb_autoloading_value(VALUE mod, ID id, VALUE* value)
if (value) {
*value = ele->value;
}
+ if (flag) {
+ *flag = ele->flag;
+ }
return 1;
}
}
@@ -2040,13 +2045,14 @@ autoload_defined_p(VALUE mod, ID id)
if (!ce || ce->value != Qundef) {
return 0;
}
- return !rb_autoloading_value(mod, id, NULL);
+ return !rb_autoloading_value(mod, id, NULL, NULL);
}
struct autoload_const_set_args {
VALUE mod;
ID id;
VALUE value;
+ rb_const_flag_t flag;
};
static void const_tbl_update(struct autoload_const_set_args *);
@@ -2093,6 +2099,7 @@ autoload_reset(VALUE arg)
args.mod = state->mod;
args.id = state->id;
args.value = state->ele->value;
+ args.flag = state->ele->flag;
safe_backup = rb_safe_level();
rb_set_safe_level_force(state->ele->safe_level);
rb_ensure(autoload_const_set, (VALUE)&args,
@@ -2239,6 +2246,7 @@ static VALUE
rb_const_search(VALUE klass, ID id, int exclude, int recurse, int visibility)
{
VALUE value, tmp, av;
+ rb_const_flag_t flag;
int mod_retry = 0;
tmp = klass;
@@ -2257,7 +2265,7 @@ rb_const_search(VALUE klass, ID id, int exclude, int recurse, int visibility)
if (value == Qundef) {
if (am == tmp) break;
am = tmp;
- if (rb_autoloading_value(tmp, id, &av)) return av;
+ if (rb_autoloading_value(tmp, id, &av, &flag)) return av;
rb_autoload_load(tmp, id);
continue;
}
@@ -2513,7 +2521,7 @@ rb_const_defined_0(VALUE klass, ID id, int exclude, int recurse, int visibility)
return (int)Qfalse;
}
if (ce->value == Qundef && !check_autoload_required(tmp, id, 0) &&
- !rb_autoloading_value(tmp, id, 0))
+ !rb_autoloading_value(tmp, id, NULL, NULL))
return (int)Qfalse;
if (exclude && tmp == rb_cObject && klass != rb_cObject) {
@@ -2599,6 +2607,7 @@ rb_const_set(VALUE klass, ID id, VALUE val)
args.mod = klass;
args.id = id;
args.value = val;
+ args.flag = CONST_PUBLIC;
const_tbl_update(&args);
}
/*
@@ -2630,6 +2639,21 @@ rb_const_set(VALUE klass, ID id, VALUE val)
}
}
+static struct autoload_data_i *
+current_autoload_data(VALUE mod, ID id)
+{
+ struct autoload_data_i *ele;
+ VALUE load = autoload_data(mod, id);
+ if (!load) return 0;
+ ele = check_autoload_data(load);
+ if (!ele) return 0;
+ /* for autoloading thread, keep the defined value to autoloading storage */
+ if (ele->state && (ele->state->thread == rb_thread_current())) {
+ return ele;
+ }
+ return 0;
+}
+
static void
const_tbl_update(struct autoload_const_set_args *args)
{
@@ -2638,19 +2662,15 @@ const_tbl_update(struct autoload_const_set_args *args)
VALUE val = args->value;
ID id = args->id;
struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
- rb_const_flag_t visibility = CONST_PUBLIC;
+ rb_const_flag_t visibility = args->flag;
rb_const_entry_t *ce;
if (rb_id_table_lookup(tbl, id, &value)) {
ce = (rb_const_entry_t *)value;
if (ce->value == Qundef) {
- VALUE load;
- struct autoload_data_i *ele;
+ struct autoload_data_i *ele = current_autoload_data(klass, id);
- load = autoload_data(klass, id);
- /* for autoloading thread, keep the defined value to autoloading storage */
- if (load && (ele = check_autoload_data(load)) && ele->state &&
- (ele->state->thread == rb_thread_current())) {
+ if (ele) {
rb_clear_constant_cache();
ele->value = val; /* autoload_i is non-WB-protected */
@@ -2739,6 +2759,13 @@ set_const_visibility(VALUE mod, int argc, const VALUE *argv,
if ((ce = rb_const_lookup(mod, id))) {
ce->flag &= ~mask;
ce->flag |= flag;
+ if (ce->value == Qundef) {
+ struct autoload_data_i *ele = current_autoload_data(mod, id);
+ if (ele) {
+ ele->flag &= ~mask;
+ ele->flag |= flag;
+ }
+ }
}
else {
if (i > 0) {
diff --git a/version.h b/version.h
index 7991e72225..f7cd4e3605 100644
--- a/version.h
+++ b/version.h
@@ -1,10 +1,10 @@
#define RUBY_VERSION "2.5.0"
-#define RUBY_RELEASE_DATE "2018-03-02"
-#define RUBY_PATCHLEVEL 39
+#define RUBY_RELEASE_DATE "2018-03-15"
+#define RUBY_PATCHLEVEL 40
#define RUBY_RELEASE_YEAR 2018
#define RUBY_RELEASE_MONTH 3
-#define RUBY_RELEASE_DAY 2
+#define RUBY_RELEASE_DAY 15
#include "ruby/version.h"
diff --git a/vm_core.h b/vm_core.h
index d1c6cd6574..cfe0042c25 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -1561,8 +1561,6 @@ void rb_vm_register_special_exception_str(enum ruby_special_exceptions sp, VALUE
void rb_gc_mark_machine_stack(const rb_execution_context_t *ec);
-int rb_autoloading_value(VALUE mod, ID id, VALUE* value);
-
void rb_vm_rewrite_cref(rb_cref_t *node, VALUE old_klass, VALUE new_klass, rb_cref_t **new_cref_ptr);
const rb_callable_method_entry_t *rb_vm_frame_method_entry(const rb_control_frame_t *cfp);
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 6eb6180a25..d4f2c2a00c 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -837,7 +837,7 @@ vm_get_ev_const(rb_execution_context_t *ec, VALUE orig_klass, ID id, int is_defi
if (am == klass) break;
am = klass;
if (is_defined) return 1;
- if (rb_autoloading_value(klass, id, &av)) return av;
+ if (rb_autoloading_value(klass, id, &av, NULL)) return av;
rb_autoload_load(klass, id);
goto search_continue;
}