1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

variable.c: flags at autoloading

* variable.c (const_tbl_update): flags by deprecate_constant /
  private_constant set during autoloading should be preserved
  after required.  [ruby-core:85516] [Bug #14469]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62395 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2018-02-13 09:36:35 +00:00
parent 8cdac548c5
commit 248ff4f1b1
2 changed files with 78 additions and 11 deletions

View file

@ -245,6 +245,46 @@ p Foo::Bar
assert_ruby_status([script], '', '[ruby-core:81016] [Bug #13526]') assert_ruby_status([script], '', '[ruby-core:81016] [Bug #13526]')
end 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) def add_autoload(path)
(@autoload_paths ||= []) << path (@autoload_paths ||= []) << path
::Object.class_eval {autoload(:AutoloadTest, path)} ::Object.class_eval {autoload(:AutoloadTest, path)}

View file

@ -1854,6 +1854,7 @@ struct autoload_state {
struct autoload_data_i { struct autoload_data_i {
VALUE feature; VALUE feature;
int safe_level; int safe_level;
rb_const_flag_t flag;
VALUE value; VALUE value;
struct autoload_state *state; /* points to on-stack struct */ struct autoload_state *state; /* points to on-stack struct */
}; };
@ -1936,6 +1937,7 @@ rb_autoload_str(VALUE mod, ID id, VALUE file)
ele->safe_level = rb_safe_level(); ele->safe_level = rb_safe_level();
ele->value = Qundef; ele->value = Qundef;
ele->state = 0; ele->state = 0;
ele->flag = CONST_PUBLIC;
st_insert(tbl, (st_data_t)id, (st_data_t)ad); st_insert(tbl, (st_data_t)id, (st_data_t)ad);
} }
@ -2011,7 +2013,7 @@ check_autoload_required(VALUE mod, ID id, const char **loadingpath)
} }
MJIT_FUNC_EXPORTED int MJIT_FUNC_EXPORTED 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; VALUE load;
struct autoload_data_i *ele; struct autoload_data_i *ele;
@ -2024,6 +2026,9 @@ rb_autoloading_value(VALUE mod, ID id, VALUE* value)
if (value) { if (value) {
*value = ele->value; *value = ele->value;
} }
if (flag) {
*flag = ele->flag;
}
return 1; return 1;
} }
} }
@ -2038,13 +2043,14 @@ autoload_defined_p(VALUE mod, ID id)
if (!ce || ce->value != Qundef) { if (!ce || ce->value != Qundef) {
return 0; return 0;
} }
return !rb_autoloading_value(mod, id, NULL); return !rb_autoloading_value(mod, id, NULL, NULL);
} }
struct autoload_const_set_args { struct autoload_const_set_args {
VALUE mod; VALUE mod;
ID id; ID id;
VALUE value; VALUE value;
rb_const_flag_t flag;
}; };
static void const_tbl_update(struct autoload_const_set_args *); static void const_tbl_update(struct autoload_const_set_args *);
@ -2091,6 +2097,7 @@ autoload_reset(VALUE arg)
args.mod = state->mod; args.mod = state->mod;
args.id = state->id; args.id = state->id;
args.value = state->ele->value; args.value = state->ele->value;
args.flag = state->ele->flag;
safe_backup = rb_safe_level(); safe_backup = rb_safe_level();
rb_set_safe_level_force(state->ele->safe_level); rb_set_safe_level_force(state->ele->safe_level);
rb_ensure(autoload_const_set, (VALUE)&args, rb_ensure(autoload_const_set, (VALUE)&args,
@ -2237,6 +2244,7 @@ static VALUE
rb_const_search(VALUE klass, ID id, int exclude, int recurse, int visibility) rb_const_search(VALUE klass, ID id, int exclude, int recurse, int visibility)
{ {
VALUE value, tmp, av; VALUE value, tmp, av;
rb_const_flag_t flag;
int mod_retry = 0; int mod_retry = 0;
tmp = klass; tmp = klass;
@ -2255,7 +2263,7 @@ rb_const_search(VALUE klass, ID id, int exclude, int recurse, int visibility)
if (value == Qundef) { if (value == Qundef) {
if (am == tmp) break; if (am == tmp) break;
am = tmp; 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); rb_autoload_load(tmp, id);
continue; continue;
} }
@ -2506,7 +2514,7 @@ rb_const_defined_0(VALUE klass, ID id, int exclude, int recurse, int visibility)
return (int)Qfalse; return (int)Qfalse;
} }
if (ce->value == Qundef && !check_autoload_required(tmp, id, 0) && 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; return (int)Qfalse;
if (exclude && tmp == rb_cObject && klass != rb_cObject) { if (exclude && tmp == rb_cObject && klass != rb_cObject) {
@ -2592,6 +2600,7 @@ rb_const_set(VALUE klass, ID id, VALUE val)
args.mod = klass; args.mod = klass;
args.id = id; args.id = id;
args.value = val; args.value = val;
args.flag = CONST_PUBLIC;
const_tbl_update(&args); const_tbl_update(&args);
} }
/* /*
@ -2623,6 +2632,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 static void
const_tbl_update(struct autoload_const_set_args *args) const_tbl_update(struct autoload_const_set_args *args)
{ {
@ -2631,19 +2655,15 @@ const_tbl_update(struct autoload_const_set_args *args)
VALUE val = args->value; VALUE val = args->value;
ID id = args->id; ID id = args->id;
struct rb_id_table *tbl = RCLASS_CONST_TBL(klass); 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; rb_const_entry_t *ce;
if (rb_id_table_lookup(tbl, id, &value)) { if (rb_id_table_lookup(tbl, id, &value)) {
ce = (rb_const_entry_t *)value; ce = (rb_const_entry_t *)value;
if (ce->value == Qundef) { if (ce->value == Qundef) {
VALUE load; struct autoload_data_i *ele = current_autoload_data(klass, id);
struct autoload_data_i *ele;
load = autoload_data(klass, id); if (ele) {
/* 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())) {
rb_clear_constant_cache(); rb_clear_constant_cache();
ele->value = val; /* autoload_i is non-WB-protected */ ele->value = val; /* autoload_i is non-WB-protected */
@ -2732,6 +2752,13 @@ set_const_visibility(VALUE mod, int argc, const VALUE *argv,
if ((ce = rb_const_lookup(mod, id))) { if ((ce = rb_const_lookup(mod, id))) {
ce->flag &= ~mask; ce->flag &= ~mask;
ce->flag |= flag; 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 { else {
if (i > 0) { if (i > 0) {