Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions class.c
Original file line number Diff line number Diff line change
Expand Up @@ -1347,8 +1347,13 @@ VALUE
rb_mod_ancestors(VALUE mod)
{
VALUE p, ary = rb_ary_new();
VALUE refined_class = Qnil;
if (FL_TEST(mod, RMODULE_IS_REFINEMENT)) {
refined_class = rb_refinement_module_get_refined_class(mod);
}

for (p = mod; p; p = RCLASS_SUPER(p)) {
if (p == refined_class) break;
if (p != RCLASS_ORIGIN(p)) continue;
if (BUILTIN_TYPE(p) == T_ICLASS) {
rb_ary_push(ary, RBASIC(p)->klass);
Expand Down Expand Up @@ -2363,12 +2368,6 @@ rb_scan_args_kw(int kw_flag, int argc, const VALUE *argv, const char *fmt, ...)
return rb_scan_args_result(&arg, argc);
}

int
rb_class_has_methods(VALUE c)
{
return rb_id_table_size(RCLASS_M_TBL(c)) == 0 ? FALSE : TRUE;
}

/*!
* \}
*/
8 changes: 7 additions & 1 deletion doc/syntax/pattern_matching.rdoc
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ Both array and hash patterns support "rest" specification:
end
#=> "matched"

In +case+ (but not in <code>=></code> and +in+) expressions, parentheses around both kinds of patterns could be omitted:
Parentheses around both kinds of patterns could be omitted:

case [1, 2]
in Integer, Integer
Expand All @@ -158,6 +158,12 @@ In +case+ (but not in <code>=></code> and +in+) expressions, parentheses around
end
#=> "matched"

[1, 2] => a, b
[1, 2] in a, b

{a: 1, b: 2, c: 3} => a:
{a: 1, b: 2, c: 3} in a:

Find pattern is similar to array pattern but it can be used to check if the given object has any elements that match the pattern:

case ["a", 1, "b", "c", 2]
Expand Down
1 change: 1 addition & 0 deletions ext/objspace/objspace.c
Original file line number Diff line number Diff line change
Expand Up @@ -998,6 +998,7 @@ Init_objspace(void)
* You can use the #type method to check the type of the internal object.
*/
rb_cInternalObjectWrapper = rb_define_class_under(rb_mObjSpace, "InternalObjectWrapper", rb_cObject);
rb_undef_alloc_func(rb_cInternalObjectWrapper);
rb_define_method(rb_cInternalObjectWrapper, "type", iow_type, 0);
rb_define_method(rb_cInternalObjectWrapper, "inspect", iow_inspect, 0);
rb_define_method(rb_cInternalObjectWrapper, "internal_object_id", iow_internal_object_id, 0);
Expand Down
1 change: 1 addition & 0 deletions ext/socket/ifaddr.c
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,7 @@ rsock_init_sockifaddr(void)
* Socket::Ifaddr represents a result of getifaddrs() function.
*/
rb_cSockIfaddr = rb_define_class_under(rb_cSocket, "Ifaddr", rb_cObject);
rb_undef_alloc_func(rb_cSockIfaddr);
rb_define_method(rb_cSockIfaddr, "inspect", ifaddr_inspect, 0);
rb_define_method(rb_cSockIfaddr, "name", ifaddr_name, 0);
rb_define_method(rb_cSockIfaddr, "ifindex", ifaddr_ifindex, 0);
Expand Down
15 changes: 13 additions & 2 deletions gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2749,11 +2749,22 @@ rb_class_allocate_instance(VALUE klass)
return obj;
}

static inline void
rb_data_object_check(VALUE klass)
{
if (klass != rb_cObject && (rb_get_alloc_func(klass) == rb_class_allocate_instance)) {
rb_undef_alloc_func(klass);
#if 0 /* TODO: enable at the next release */
rb_warn("undefining the allocator of T_DATA class %"PRIsVALUE, klass);
#endif
}
}

VALUE
rb_data_object_wrap(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree)
{
RUBY_ASSERT_ALWAYS(dfree != (RUBY_DATA_FUNC)1);
if (klass) Check_Type(klass, T_CLASS);
if (klass) rb_data_object_check(klass);
return newobj_of(klass, T_DATA, (VALUE)dmark, (VALUE)dfree, (VALUE)datap, FALSE, sizeof(RVALUE));
}

Expand All @@ -2769,7 +2780,7 @@ VALUE
rb_data_typed_object_wrap(VALUE klass, void *datap, const rb_data_type_t *type)
{
RUBY_ASSERT_ALWAYS(type);
if (klass) Check_Type(klass, T_CLASS);
if (klass) rb_data_object_check(klass);
return newobj_of(klass, T_DATA, (VALUE)type, (VALUE)1, (VALUE)datap, type->flags & RUBY_FL_WB_PROTECTED, sizeof(RVALUE));
}

Expand Down
23 changes: 0 additions & 23 deletions hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,6 @@
#include "gc.h"
#endif

#define HAS_EXTRA_STATES(hash, klass) ( \
((klass = has_extra_methods(rb_obj_class(hash))) != 0) || \
FL_TEST((hash), FL_EXIVAR|RHASH_PROC_DEFAULT) || \
!NIL_P(RHASH_IFNONE(hash)))

#define SET_DEFAULT(hash, ifnone) ( \
FL_UNSET_RAW(hash, RHASH_PROC_DEFAULT), \
RHASH_SET_IFNONE(hash, ifnone))
Expand All @@ -73,18 +68,6 @@ copy_default(struct RHash *hash, const struct RHash *hash2)
RHASH_SET_IFNONE(hash, RHASH_IFNONE((VALUE)hash2));
}

static VALUE
has_extra_methods(VALUE klass)
{
const VALUE base = rb_cHash;
VALUE c = klass;
while (c != base) {
if (rb_class_has_methods(c)) return klass;
c = RCLASS_SUPER(c);
}
return 0;
}

static VALUE rb_hash_s_try_convert(VALUE, VALUE);

/*
Expand Down Expand Up @@ -2608,12 +2591,6 @@ rb_hash_reject(VALUE hash)
VALUE result;

RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
if (RTEST(ruby_verbose)) {
VALUE klass;
if (HAS_EXTRA_STATES(hash, klass)) {
rb_warn("extra states are no longer copied: %+"PRIsVALUE, hash);
}
}
result = hash_dup_with_compare_by_id(hash);
if (!RHASH_EMPTY_P(hash)) {
rb_hash_foreach(result, delete_if_i, result);
Expand Down
1 change: 0 additions & 1 deletion internal/class.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@ VALUE rb_obj_public_methods(int argc, const VALUE *argv, VALUE obj);
VALUE rb_special_singleton_class(VALUE);
VALUE rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach);
VALUE rb_singleton_class_get(VALUE obj);
int rb_class_has_methods(VALUE c);
void rb_undef_methods_from(VALUE klass, VALUE super);

static inline void RCLASS_SET_ORIGIN(VALUE klass, VALUE origin);
Expand Down
4 changes: 2 additions & 2 deletions parse.y
Original file line number Diff line number Diff line change
Expand Up @@ -1732,7 +1732,7 @@ expr : command_call
p->ctxt.in_kwarg = 1;
}
{$<tbl>$ = push_pvtbl(p);}
p_expr
p_top_expr_body
{pop_pvtbl(p, $<tbl>4);}
{
p->ctxt.in_kwarg = $<ctxt>3.in_kwarg;
Expand All @@ -1750,7 +1750,7 @@ expr : command_call
p->ctxt.in_kwarg = 1;
}
{$<tbl>$ = push_pvtbl(p);}
p_expr
p_top_expr_body
{pop_pvtbl(p, $<tbl>4);}
{
p->ctxt.in_kwarg = $<ctxt>3.in_kwarg;
Expand Down
14 changes: 14 additions & 0 deletions spec/ruby/language/pattern_matching_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1135,5 +1135,19 @@ def ===(obj)
result.should == true
end
end

ruby_version_is "3.1" do
it "can omit parentheses in one line pattern matching" do
eval(<<~RUBY).should == [1, 2]
[1, 2] => a, b
[a, b]
RUBY

eval(<<~RUBY).should == 1
{a: 1} => a:
a
RUBY
end
end
end
end
9 changes: 0 additions & 9 deletions test/ruby/test_hash.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2048,21 +2048,12 @@ def test_huge_iter_level

class TestSubHash < TestHash
class SubHash < Hash
def reject(*)
super
end
end

def setup
@cls = SubHash
super
end

def test_reject
assert_warning(/extra states are no longer copied/) do
super
end
end
end

ruby2_keywords def get_flagged_hash(*args)
Expand Down
14 changes: 7 additions & 7 deletions test/ruby/test_pattern_matching.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1519,13 +1519,13 @@ def test_one_line
assert_raise(NoMatchingPatternError) do
{a: 1} => {a: 0}
end
assert_syntax_error("if {} => {a:}; end", /void value expression/)
assert_syntax_error(%q{
1 => a, b
}, /unexpected/, '[ruby-core:95098]')
assert_syntax_error(%q{
1 => a:
}, /unexpected/, '[ruby-core:95098]')

[1, 2] => a, b
assert_equal 1, a
assert_equal 2, b

{a: 1} => a:
assert_equal 1, a

assert_equal true, (1 in 1)
assert_equal false, (1 in 2)
Expand Down
12 changes: 12 additions & 0 deletions test/ruby/test_refinement.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2559,6 +2559,18 @@ def test_privatizing_refined_method
assert_equal(:refined, Bug17822::Client.call_foo)
end

def test_ancestors
refinement = nil
as = nil
Module.new do
refine Array do
refinement = self
as = ancestors
end
end
assert_equal([refinement], as, "[ruby-core:86949] [Bug #14744]")
end

private

def eval_using(mod, s)
Expand Down
18 changes: 14 additions & 4 deletions tool/mkrunnable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ def ln_safe(src, dest)

alias ln_dir_safe ln_safe

case RUBY_PLATFORM
when /linux/
def ln_exe(src, dest)
ln(src, dest, force: true)
end
else
alias ln_exe ln_safe
end

if !File.respond_to?(:symlink) && /mingw|mswin/ =~ (CROSS_COMPILING || RUBY_PLATFORM)
extend Mswin
end
Expand Down Expand Up @@ -80,10 +89,11 @@ def relative_path_from(path, base)
end
end

def ln_relative(src, dest)
def ln_relative(src, dest, executable = false)
return if File.identical?(src, dest)
parent = File.dirname(dest)
File.directory?(parent) or mkdir_p(parent)
return ln_exe(src, dest) if executable
clean_link(relative_path_from(src, parent), dest) {|s, d| ln_safe(s, d)}
end

Expand Down Expand Up @@ -116,9 +126,9 @@ def ln_dir_relative(src, dest)
rubyw_install_name = config["rubyw_install_name"]
goruby_install_name = "go" + ruby_install_name
[ruby_install_name, rubyw_install_name, goruby_install_name].map do |ruby|
ruby += exeext
if ruby and !ruby.empty? and !File.file?(target = "#{bindir}/#{ruby}")
ln_relative(ruby, target)
if ruby and !ruby.empty?
ruby += exeext
ln_relative(ruby, "#{bindir}/#{ruby}", true)
end
end
so = config["LIBRUBY_SO"]
Expand Down
2 changes: 1 addition & 1 deletion version.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

#define RUBY_RELEASE_YEAR 2021
#define RUBY_RELEASE_MONTH 8
#define RUBY_RELEASE_DAY 19
#define RUBY_RELEASE_DAY 20

#include "ruby/version.h"

Expand Down