diff --git a/.github/workflows/mingw.yml b/.github/workflows/mingw.yml
index ce53e33aaea46c..1c4cb533d3f3c7 100644
--- a/.github/workflows/mingw.yml
+++ b/.github/workflows/mingw.yml
@@ -65,10 +65,39 @@ jobs:
)}}
steps:
- - name: Set up Ruby & MSYS2
- uses: ruby/setup-ruby@d8d83c3960843afb664e821fed6be52f37da5267 # v1.231.0
+ - uses: msys2/setup-msys2@40677d36a502eb2cf0fb808cc9dec31bf6152638 # v2.28.0
+ id: msys2
with:
- ruby-version: '3.2'
+ msystem: UCRT64
+ update: true
+ install: >-
+ git
+ make
+ ruby
+ autoconf
+ mingw-w64-ucrt-x86_64-gcc
+ mingw-w64-ucrt-x86_64-ragel
+ mingw-w64-ucrt-x86_64-openssl
+ mingw-w64-ucrt-x86_64-libyaml
+ mingw-w64-ucrt-x86_64-libffi
+
+ - name: Set up env
+ id: setup-env
+ working-directory:
+ run: |
+ $msys2 = ${env:MSYS2_LOCATION}
+ echo $msys2\usr\bin $msys2\ucrt64\bin |
+ Tee-Object ${env:GITHUB_PATH} -Append -Encoding utf-8
+
+ # Use the fast device for the temporary directory.
+ # %TEMP% is inconsistent with %TMP% and test-all expects they are consistent.
+ # https://github.com/actions/virtual-environments/issues/712#issuecomment-613004302
+ $tmp = ${env:RUNNER_TEMP}
+ echo HOME=$home TMP=$tmp TEMP=$tmp TMPDIR=$tmp |
+ Tee-Object ${env:GITHUB_ENV} -Append -Encoding utf-8
+ shell: pwsh # cmd.exe does not strip spaces before `|`.
+ env:
+ MSYS2_LOCATION: ${{ steps.msys2.outputs.msys2-location }}
- name: Remove Strawberry Perl pkg-config
working-directory:
@@ -86,25 +115,38 @@ jobs:
- name: Misc system & package info
working-directory:
run: |
- # show where
- result=true
- for e in gcc.exe ragel.exe make.exe libcrypto-3-x64.dll libssl-3-x64.dll; do
- echo ::group::$'\e[93m'$e$'\e[m'
- where $e || result=false
- echo ::endgroup::
- done
- # show version
- for e in gcc ragel make "openssl version"; do
- case "$e" in *" "*) ;; *) e="$e --version";; esac
- echo ::group::$'\e[93m'$e$'\e[m'
- $e || result=false
- echo ::endgroup::
- done
- # show packages
- echo ::group::$'\e[93m'Packages$'\e[m'
- pacman -Qs mingw-w64-ucrt-x86_64-* | sed -n "s,local/mingw-w64-ucrt-x86_64-,,p"
- echo ::endgroup::
- $result
+ group() { echo ::group::$'\e[94;1m'"$*"$'\e[m'; }
+ endgroup() { echo ::endgroup::; }
+
+ group Path
+ cygpath -wa / . $(type -p cygpath bash sh)
+ endgroup
+
+ I() {
+ group $1
+ run Where type -pa $1 && { [ $# -eq 1 ] || run Version "$@"; } ||
+ failed+=($1)
+ endgroup
+ }
+ run() { local w m=$1; shift; w="$("$@")" && show "$m" && indent "$w"; }
+ indent() { [ -z "$1" ] || echo "$1" | /bin/sed '/^$/!s/^/ /'; }
+ show() { echo $'\e[96m'"$*"$'\e[m'; }
+
+ failed=()
+
+ I gcc.exe --version
+ I ragel.exe --version
+ I make.exe --version
+ I openssl.exe version
+ I libcrypto-3-x64.dll
+ I libssl-3-x64.dll
+
+ group Packages
+ pacman -Qs mingw-w64-ucrt-x86_64-* | /bin/sed -n "s,local/mingw-w64-ucrt-x86_64-,,p"
+ endgroup
+
+ [ ${#failed[@]} -eq 0 ]
+ shell: sh
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
@@ -123,6 +165,7 @@ jobs:
run: >
../src/configure --disable-install-doc --prefix=/.
--build=$CHOST --host=$CHOST --target=$CHOST
+ shell: sh
- name: make all
timeout-minutes: 30
@@ -145,7 +188,6 @@ jobs:
- name: test
timeout-minutes: 30
run: make test
- shell: cmd
env:
GNUMAKEFLAGS: ''
RUBY_TESTOPTS: '-v --tty=no'
@@ -153,7 +195,6 @@ jobs:
- name: test-all
timeout-minutes: 45
- shell: cmd
run: |
make ${{ StartsWith(matrix.test_task, 'test/') && matrix.test_task || 'test-all' }}
env:
@@ -168,7 +209,6 @@ jobs:
timeout-minutes: 10
run: |
make ${{ StartsWith(matrix.test_task, 'spec/') && matrix.test_task || 'test-spec' }}
- shell: cmd
if: ${{ matrix.test_task == 'check' || matrix.test_task == 'test-spec' || StartsWith(matrix.test_task, 'spec/') }}
- uses: ./src/.github/actions/slack
@@ -180,4 +220,4 @@ jobs:
defaults:
run:
working-directory: build
- shell: sh
+ shell: cmd
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 053c37ec5d9f23..d7c88393be52e0 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -39,7 +39,7 @@ jobs:
test_task: test-bundled-gems
fail-fast: false
- runs-on: windows-${{ matrix.os < 2022 && '2019' || matrix.os }}
+ runs-on: windows-${{ matrix.os }}
if: >-
${{!(false
@@ -94,7 +94,7 @@ jobs:
- name: Install libraries with vcpkg
run: |
- vcpkg install --vcpkg-root=C:\Users\runneradmin\scoop\apps\vcpkg\current
+ vcpkg install --vcpkg-root=%USERPROFILE%\scoop\apps\vcpkg\current
working-directory: src
- name: Save vcpkg artifact
@@ -184,7 +184,7 @@ jobs:
- name: Set up Launchable
uses: ./.github/actions/launchable/setup
with:
- os: windows-${{ matrix.os < 2022 && '2019' || matrix.os }}
+ os: windows-${{ matrix.os }}
launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }}
builddir: build
srcdir: src
diff --git a/ast.c b/ast.c
index bc2adeacd630a4..04b954385477e1 100644
--- a/ast.c
+++ b/ast.c
@@ -866,6 +866,12 @@ node_locations(VALUE ast_value, const NODE *node)
location_new(&RNODE_IF(node)->if_keyword_loc),
location_new(&RNODE_IF(node)->then_keyword_loc),
location_new(&RNODE_IF(node)->end_keyword_loc));
+ case NODE_IN:
+ return rb_ary_new_from_args(4,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_IN(node)->in_keyword_loc),
+ location_new(&RNODE_IN(node)->then_keyword_loc),
+ location_new(&RNODE_IN(node)->operator_loc));
case NODE_MODULE:
return rb_ary_new_from_args(3,
location_new(nd_code_loc(node)),
diff --git a/benchmark/string_casecmp.yml b/benchmark/string_casecmp.yml
index 2354040a049e3f..88a3555c8a8837 100644
--- a/benchmark/string_casecmp.yml
+++ b/benchmark/string_casecmp.yml
@@ -20,7 +20,9 @@ benchmark:
casecmp-10: lstr10.casecmp(ustr10)
casecmp-100: lstr100.casecmp(ustr100)
casecmp-1000: lstr1000.casecmp(ustr1000)
+ casecmp-1000vs10: lstr1000.casecmp(ustr10)
casecmp-nonascii1: lnonascii1.casecmp(unonascii1)
casecmp-nonascii10: lnonascii10.casecmp(unonascii10)
casecmp-nonascii100: lnonascii100.casecmp(unonascii100)
casecmp-nonascii1000: lnonascii1000.casecmp(unonascii1000)
+ casecmp-nonascii1000vs10: lnonascii1000.casecmp(unonascii10)
diff --git a/doc/ruby/options.md b/doc/ruby/options.md
index bfbd2530de397e..95f8cf453c9f14 100644
--- a/doc/ruby/options.md
+++ b/doc/ruby/options.md
@@ -672,6 +672,11 @@ $ ruby --internal-encoding=cesu-8 -e 'puts Encoding::default_internal'
CESU-8
```
+### `--jit`
+
+Option `--jit` is an alias for option `--yjit`, which enables YJIT;
+see additional YJIT options in the [YJIT documentation](rdoc-ref:yjit/yjit.md).
+
### `--verbose`: Set `$VERBOSE`
Option `--verbose` sets global variable `$VERBOSE` to `true`
@@ -681,44 +686,3 @@ and disables input from `$stdin`.
Option `--version` prints the version of the Ruby interpreter, then exits.
-## Experimental Options
-
-These options are experimental in the current Ruby release,
-and may be modified or withdrawn in later releases.
-
-### `--jit`
-
-Option `-jit` enables JIT compilation with the default option.
-
-#### `--jit-debug`
-
-Option `--jit-debug` enables JIT debugging (very slow);
-adds compiler flags if given.
-
-#### `--jit-max-cache=num`
-
-Option `--jit-max-cache=num` sets the maximum number of methods
-to be JIT-ed in a cache; default: 100).
-
-#### `--jit-min-calls=num`
-
-Option `jit-min-calls=num` sets the minimum number of calls to trigger JIT
-(for testing); default: 10000).
-
-#### `--jit-save-temps`
-
-Option `--jit-save-temps` saves JIT temporary files in $TMP or /tmp (for testing).
-
-#### `--jit-verbose`
-
-Option `--jit-verbose` prints JIT logs of level `num` or less
-to `$stderr`; default: 0.
-
-#### `--jit-wait`
-
-Option `--jit-wait` waits until JIT compilation finishes every time (for testing).
-
-#### `--jit-warnings`
-
-Option `--jit-warnings` enables printing of JIT warnings.
-
diff --git a/doc/windows.md b/doc/windows.md
index 13c797875e6a3d..4ea03d0507d2b7 100644
--- a/doc/windows.md
+++ b/doc/windows.md
@@ -99,16 +99,18 @@ sh ../../ruby/configure -C --disable-install-doc --with-opt-dir=C:\Users\usernam
To cross build arm64 binary:
```
- cmd /k win32\vssetup.cmd -arch arm64
+ cmd /k win32\vssetup.cmd -arch=arm64
```
To cross build x64 binary:
```
- cmd /k win32\vssetup.cmd -arch x64
+ cmd /k win32\vssetup.cmd -arch=x64
```
- See `win32\vssetup.cmd -help` for other command line options.
+ This batch file is a wrapper of `vsdevcmd.bat` and options are
+ passed to it as-is. `win32\vssetup.cmd -help` for other command
+ line options.
**Note** building ruby requires following commands.
diff --git a/gc.c b/gc.c
index 4c8a042c1e8513..7663e82f41b5ab 100644
--- a/gc.c
+++ b/gc.c
@@ -4357,7 +4357,7 @@ gc_config_set(rb_execution_context_t *ec, VALUE self, VALUE hash)
rb_gc_impl_config_set(objspace, hash);
- return rb_gc_impl_config_get(objspace);
+ return Qnil;
}
static VALUE
diff --git a/gc.rb b/gc.rb
index 1298e3005660b6..603520df5312ab 100644
--- a/gc.rb
+++ b/gc.rb
@@ -258,83 +258,71 @@ def self.stat_heap heap_name = nil, hash_or_key = nil
# call-seq:
# GC.config -> hash
- # GC.config(hash) -> hash
+ # GC.config(hash_to_merge) -> merged_hash
#
- # Sets or gets information about the current \GC config.
+ # This method is implementation-specific to CRuby.
#
- # Configuration parameters are \GC implementation-specific and may change
- # without notice.
+ # Sets or gets information about the current \GC configuration.
#
- # This method can be called without parameters to retrieve the current config
- # as a +Hash+ with +Symbol+ keys.
+ # Configuration parameters are \GC implementation-specific and may change without notice.
#
- # This method can also be called with a +Hash+ argument to assign values to
- # valid config keys. Config keys missing from the passed +Hash+ will be left
- # unmodified.
+ # With no argument given, returns a hash containing the configuration:
#
- # If a key/value pair is passed to this function that does not correspond to
- # a valid config key for the \GC implementation being used, no config will be
- # updated, the key will be present in the returned Hash, and its value will
- # be +nil+. This is to facilitate easy migration between \GC implementations.
+ # GC.config
+ # # => {rgengc_allow_full_mark: true, implementation: "default"}
#
- # In both call-seqs, the return value of GC.config will be a +Hash+
- # containing the most recent full configuration, i.e., all keys and values
- # defined by the specific \GC implementation being used. In the case of a
- # config update, the return value will include the new values being updated.
+ # With argument +hash_to_merge+ given,
+ # merges that hash into the stored configuration hash;
+ # ignores unknown hash keys;
+ # returns the implementation-specific configuration hash (see below):
#
- # This method is only expected to work on CRuby.
- #
- # === \GC Implementation independent values
- #
- # The GC.config hash can also contain keys that are global and
- # read-only. These keys are not specific to any one \GC library implementation
- # and attempting to write to them will raise +ArgumentError+.
+ # GC.config(rgengc_allow_full_mark: false)
+ # # => {rgengc_allow_full_mark: false}
+ # GC.config
+ # # => {rgengc_allow_full_mark: false, implementation: "default"}
+ # GC.config(foo: 'bar')
+ # # => {rgengc_allow_full_mark: false}
+ # GC.config
+ # # => {rgengc_allow_full_mark: false, implementation: "default"}
#
- # There is currently only one global, read-only key:
+ # All-Implementations Configuration
#
- # [implementation]
- # Returns a +String+ containing the name of the currently loaded \GC library,
- # if one has been loaded using +RUBY_GC_LIBRARY+, and "default" in all other
- # cases
+ # The single read-only entry for all implementations is:
#
- # === \GC Implementation specific values
+ # - +implementation+:
+ # the string name of the implementation;
+ # for the Ruby default implementation, 'default'.
#
- # \GC libraries are expected to document their own configuration. Valid keys
- # for Ruby's default \GC implementation are:
+ # Implementation-Specific Configuration
#
- # [rgengc_allow_full_mark]
- # Controls whether the \GC is allowed to run a full mark (young & old objects).
+ # A \GC implementation maintains its own implementation-specific configuration.
#
- # When +true+, \GC interleaves major and minor collections. This is the default. \GC
- # will function as intended.
+ # For Ruby's default implementation the single entry is:
#
- # When +false+, the \GC will never trigger a full marking cycle unless
- # explicitly requested by user code. Instead, only a minor mark will run—
- # only young objects will be marked. When the heap space is exhausted, new
- # pages will be allocated immediately instead of running a full mark.
+ # - +rgengc_allow_full_mark+:
+ # Controls whether the \GC is allowed to run a full mark (young & old objects):
#
- # A flag will be set to notify that a full mark has been
- # requested. This flag is accessible using
- # GC.latest_gc_info(:need_major_by)
+ # - +true+ (default): \GC interleaves major and minor collections.
+ # A flag is set to notify GC that a full mark has been requested.
+ # This flag is accessible via GC.latest_gc_info(:need_major_by).
+ # - +false+: \GC does not initiate a full marking cycle unless explicitly directed by user code;
+ # see GC.start.
+ # Setting this parameter to +false+ disables young-to-old promotion.
+ # For performance reasons, we recommended warming up the application using Process.warmup
+ # before setting this parameter to +false+.
#
- # The user can trigger a major collection at any time using
- # GC.start(full_mark: true)
- #
- # When +false+, Young to Old object promotion is disabled. For performance
- # reasons, it is recommended to warm up an application using +Process.warmup+
- # before setting this parameter to +false+.
def self.config hash = nil
- return Primitive.gc_config_get unless hash
-
- if(Primitive.cexpr!("RBOOL(RB_TYPE_P(hash, T_HASH))"))
+ if Primitive.cexpr!("RBOOL(RB_TYPE_P(hash, T_HASH))")
if hash.include?(:implementation)
raise ArgumentError, 'Attempting to set read-only key "Implementation"'
end
Primitive.gc_config_set hash
- else
+ elsif hash != nil
raise ArgumentError
end
+
+ Primitive.gc_config_get
end
# call-seq:
diff --git a/node_dump.c b/node_dump.c
index c318baeeede009..18ac3d7b35b4e5 100644
--- a/node_dump.c
+++ b/node_dump.c
@@ -309,8 +309,11 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("example: case x; in 1; foo; in 2; bar; else baz; end");
F_NODE(nd_head, RNODE_IN, "in pattern");
F_NODE(nd_body, RNODE_IN, "in body");
- LAST_NODE;
F_NODE(nd_next, RNODE_IN, "next in clause");
+ F_LOC(in_keyword_loc, RNODE_IN);
+ F_LOC(then_keyword_loc, RNODE_IN);
+ LAST_NODE;
+ F_LOC(operator_loc, RNODE_IN);
return;
case NODE_WHILE:
diff --git a/parse.y b/parse.y
index e77dc790bcd1cd..c0f46a395f9f59 100644
--- a/parse.y
+++ b/parse.y
@@ -1070,7 +1070,7 @@ static rb_node_case_t *rb_node_case_new(struct parser_params *p, NODE *nd_head,
static rb_node_case2_t *rb_node_case2_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *case_keyword_loc, const YYLTYPE *end_keyword_loc);
static rb_node_case3_t *rb_node_case3_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *case_keyword_loc, const YYLTYPE *end_keyword_loc);
static rb_node_when_t *rb_node_when_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *then_keyword_loc);
-static rb_node_in_t *rb_node_in_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc);
+static rb_node_in_t *rb_node_in_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc, const YYLTYPE *in_keyword_loc, const YYLTYPE *then_keyword_loc, const YYLTYPE *operator_loc);
static rb_node_while_t *rb_node_while_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *closing_loc);
static rb_node_until_t *rb_node_until_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *closing_loc);
static rb_node_iter_t *rb_node_iter_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body, const YYLTYPE *loc);
@@ -1178,7 +1178,7 @@ static rb_node_error_t *rb_node_error_new(struct parser_params *p, const YYLTYPE
#define NEW_CASE2(b,loc,ck_loc,ek_loc) (NODE *)rb_node_case2_new(p,b,loc,ck_loc,ek_loc)
#define NEW_CASE3(h,b,loc,ck_loc,ek_loc) (NODE *)rb_node_case3_new(p,h,b,loc,ck_loc,ek_loc)
#define NEW_WHEN(c,t,e,loc,k_loc,t_loc) (NODE *)rb_node_when_new(p,c,t,e,loc,k_loc,t_loc)
-#define NEW_IN(c,t,e,loc) (NODE *)rb_node_in_new(p,c,t,e,loc)
+#define NEW_IN(c,t,e,loc,ik_loc,tk_loc,o_loc) (NODE *)rb_node_in_new(p,c,t,e,loc,ik_loc,tk_loc,o_loc)
#define NEW_WHILE(c,b,n,loc,k_loc,c_loc) (NODE *)rb_node_while_new(p,c,b,n,loc,k_loc,c_loc)
#define NEW_UNTIL(c,b,n,loc,k_loc,c_loc) (NODE *)rb_node_until_new(p,c,b,n,loc,k_loc,c_loc)
#define NEW_ITER(a,b,loc) (NODE *)rb_node_iter_new(p,a,b,loc)
@@ -3472,7 +3472,7 @@ expr : command_call
pop_pktbl(p, $p_pktbl);
pop_pvtbl(p, $p_pvtbl);
p->ctxt.in_kwarg = $ctxt.in_kwarg;
- $$ = NEW_CASE3($arg, NEW_IN($body, 0, 0, &@body), &@$, &NULL_LOC, &NULL_LOC);
+ $$ = NEW_CASE3($arg, NEW_IN($body, 0, 0, &@body, &NULL_LOC, &NULL_LOC, &@2), &@$, &NULL_LOC, &NULL_LOC);
/*% ripper: case!($:arg, in!($:body, Qnil, Qnil)) %*/
}
| arg keyword_in
@@ -3485,7 +3485,7 @@ expr : command_call
pop_pktbl(p, $p_pktbl);
pop_pvtbl(p, $p_pvtbl);
p->ctxt.in_kwarg = $ctxt.in_kwarg;
- $$ = NEW_CASE3($arg, NEW_IN($body, NEW_TRUE(&@body), NEW_FALSE(&@body), &@body), &@$, &NULL_LOC, &NULL_LOC);
+ $$ = NEW_CASE3($arg, NEW_IN($body, NEW_TRUE(&@body), NEW_FALSE(&@body), &@body, &@keyword_in, &NULL_LOC, &NULL_LOC), &@$, &NULL_LOC, &NULL_LOC);
/*% ripper: case!($:arg, in!($:body, Qnil, Qnil)) %*/
}
| arg %prec tLBRACE_ARG
@@ -5399,7 +5399,7 @@ p_case_body : keyword_in
compstmt(stmts)
p_cases[cases]
{
- $$ = NEW_IN($expr, $compstmt, $cases, &@$);
+ $$ = NEW_IN($expr, $compstmt, $cases, &@$, &@keyword_in, &@then, &NULL_LOC);
/*% ripper: in!($:expr, $:compstmt, $:cases) %*/
}
;
@@ -11528,12 +11528,15 @@ rb_node_when_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd
}
static rb_node_in_t *
-rb_node_in_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc)
+rb_node_in_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc, const YYLTYPE *in_keyword_loc, const YYLTYPE *then_keyword_loc, const YYLTYPE *operator_loc)
{
rb_node_in_t *n = NODE_NEWNODE(NODE_IN, rb_node_in_t, loc);
n->nd_head = nd_head;
n->nd_body = nd_body;
n->nd_next = nd_next;
+ n->in_keyword_loc = *in_keyword_loc;
+ n->then_keyword_loc = *then_keyword_loc;
+ n->operator_loc = *operator_loc;
return n;
}
diff --git a/rubyparser.h b/rubyparser.h
index e436d1c404b2a2..cc63efd3f85998 100644
--- a/rubyparser.h
+++ b/rubyparser.h
@@ -324,6 +324,9 @@ typedef struct RNode_IN {
struct RNode *nd_head;
struct RNode *nd_body;
struct RNode *nd_next;
+ rb_code_location_t in_keyword_loc;
+ rb_code_location_t then_keyword_loc;
+ rb_code_location_t operator_loc;
} rb_node_in_t;
typedef struct RNode_LOOP {
diff --git a/string.c b/string.c
index fe848d6a4a821c..96a9f96bd3432b 100644
--- a/string.c
+++ b/string.c
@@ -4381,9 +4381,9 @@ str_casecmp(VALUE str1, VALUE str2)
p2 += l2;
}
}
- if (RSTRING_LEN(str1) == RSTRING_LEN(str2)) return INT2FIX(0);
- if (RSTRING_LEN(str1) > RSTRING_LEN(str2)) return INT2FIX(1);
- return INT2FIX(-1);
+ if (p1 == p1end && p2 == p2end) return INT2FIX(0);
+ if (p1 == p1end) return INT2FIX(-1);
+ return INT2FIX(1);
}
/*
diff --git a/test/ruby/test_ast.rb b/test/ruby/test_ast.rb
index 6372b0d34e5e71..9a7d75c270b661 100644
--- a/test/ruby/test_ast.rb
+++ b/test/ruby/test_ast.rb
@@ -1514,6 +1514,20 @@ def test_if_locations
assert_locations(node.children[-1].children[1].children[0].locations, [[1, 11, 1, 17], [1, 13, 1, 15], nil, nil])
end
+ def test_in_locations
+ node = ast_parse("case 1; in 2 then 3; end")
+ assert_locations(node.children[-1].children[1].locations, [[1, 8, 1, 20], [1, 8, 1, 10], [1, 13, 1, 17], nil])
+
+ node = ast_parse("1 => a")
+ assert_locations(node.children[-1].children[1].locations, [[1, 5, 1, 6], nil, nil, [1, 2, 1, 4]])
+
+ node = ast_parse("1 in a")
+ assert_locations(node.children[-1].children[1].locations, [[1, 5, 1, 6], [1, 2, 1, 4], nil, nil])
+
+ node = ast_parse("case 1; in 2; 3; end")
+ assert_locations(node.children[-1].children[1].locations, [[1, 8, 1, 16], [1, 8, 1, 10], [1, 12, 1, 13], nil])
+ end
+
def test_next_locations
node = ast_parse("loop { next 1 }")
assert_locations(node.children[-1].children[-1].children[-1].locations, [[1, 7, 1, 13], [1, 7, 1, 11]])
diff --git a/test/ruby/test_gc.rb b/test/ruby/test_gc.rb
index 85022cbc4d8924..ccccd212b692eb 100644
--- a/test/ruby/test_gc.rb
+++ b/test/ruby/test_gc.rb
@@ -75,12 +75,9 @@ def test_gc_config_setting_returns_updated_config_hash
GC.start
end
- def test_gc_config_setting_returns_nil_for_missing_keys
- missing_value = GC.config(no_such_key: true)[:no_such_key]
- assert_nil(missing_value)
- ensure
- GC.config(full_mark: true)
- GC.start
+ def test_gc_config_setting_returns_config_hash
+ hash = GC.config(no_such_key: true)
+ assert_equal(GC.config, hash)
end
def test_gc_config_disable_major
diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb
index 8fb57bd58e6111..c7e4b0c1ec7fee 100644
--- a/test/ruby/test_string.rb
+++ b/test/ruby/test_string.rb
@@ -2832,16 +2832,32 @@ def test_compare_different_encoding_string
def test_casecmp
assert_equal(0, S("FoO").casecmp("fOO"))
assert_equal(1, S("FoO").casecmp("BaR"))
+ assert_equal(-1, S("foo").casecmp("FOOBAR"))
assert_equal(-1, S("baR").casecmp("FoO"))
assert_equal(1, S("\u3042B").casecmp("\u3042a"))
assert_equal(-1, S("foo").casecmp("foo\0"))
+ assert_equal(1, S("FOOBAR").casecmp("foo"))
+ assert_equal(0, S("foo\0bar").casecmp("FOO\0BAR"))
assert_nil(S("foo").casecmp(:foo))
assert_nil(S("foo").casecmp(Object.new))
+ assert_nil(S("foo").casecmp(0))
+ assert_nil(S("foo").casecmp(5.00))
+
o = Object.new
def o.to_str; "fOO"; end
assert_equal(0, S("FoO").casecmp(o))
+
+ assert_equal(0, S("#" * 128 + "A" * 256 + "b").casecmp("#" * 128 + "a" * 256 + "B"))
+ assert_equal(0, S("a" * 256 + "B").casecmp("A" * 256 + "b"))
+
+ assert_equal(-1, S("@").casecmp("`"))
+ assert_equal(0, S("hello\u00E9X").casecmp("HELLO\u00E9x"))
+
+ s1 = S("\xff".force_encoding("UTF-8"))
+ s2 = S("\xff".force_encoding("ISO-2022-JP"))
+ assert_nil(s1.casecmp(s2))
end
def test_casecmp?
@@ -2854,9 +2870,16 @@ def test_casecmp?
assert_nil(S("foo").casecmp?(:foo))
assert_nil(S("foo").casecmp?(Object.new))
+ assert_nil(S("foo").casecmp(0))
+ assert_nil(S("foo").casecmp(5.00))
+
o = Object.new
def o.to_str; "fOO"; end
assert_equal(true, S("FoO").casecmp?(o))
+
+ s1 = S("\xff".force_encoding("UTF-8"))
+ s2 = S("\xff".force_encoding("ISO-2022-JP"))
+ assert_nil(s1.casecmp?(s2))
end
def test_upcase2
diff --git a/win32/vssetup.cmd b/win32/vssetup.cmd
index be77c87b294a6c..1ff0a7d10ab6f4 100755
--- a/win32/vssetup.cmd
+++ b/win32/vssetup.cmd
@@ -1,27 +1,27 @@
-@echo off
-setlocal ENABLEEXTENSIONS
+@setlocal ENABLEEXTENSIONS
+::- do not `echo off` that affects the called batch files
::- check for vswhere
-set vswhere=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe
-if not exist "%vswhere%" (
+@set vswhere=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe
+@if not exist "%vswhere%" (
echo 1>&2 vswhere.exe not found
exit /b 1
)
::- find the latest build tool and its setup batch file.
-set VSDEVCMD=
-for /f "delims=" %%I in ('"%vswhere%" -products * -latest -property installationPath') do (
+@set VSDEVCMD=
+@for /f "delims=" %%I in ('"%vswhere%" -products * -latest -property installationPath') do @(
set VSDEVCMD=%%I\Common7\Tools\VsDevCmd.bat
)
-if not defined VSDEVCMD (
+@if not defined VSDEVCMD (
echo 1>&2 Visual Studio not found
exit /b 1
)
::- default to the current processor.
-set arch=%PROCESSOR_ARCHITECTURE%
+@set arch=%PROCESSOR_ARCHITECTURE%
::- `vsdevcmd.bat` requires arch names to be lowercase
-for %%i in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do @(
+@for %%i in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do @(
call set arch=%%arch:%%i=%%i%%
)
-echo on && endlocal && "%VSDEVCMD%" -arch=%arch% -host_arch=%arch% %*
+@(endlocal && "%VSDEVCMD%" -arch=%arch% -host_arch=%arch% %*)