[前][次][番号順一覧][スレッド一覧]

ruby-changes:67164

From: Kazuki <ko1@a...>
Date: Sun, 15 Aug 2021 10:34:54 +0900 (JST)
Subject: [ruby-changes:67164] 4568ba0711 (master): Show verbose error messages when single pattern match fails

https://git.ruby-lang.org/ruby.git/commit/?id=4568ba0711

From 4568ba071107a139b9f02fc17aa12f998181abf1 Mon Sep 17 00:00:00 2001
From: Kazuki Tsujimoto <kazuki@c...>
Date: Sun, 15 Aug 2021 09:38:24 +0900
Subject: Show verbose error messages when single pattern match fails

    [0] => [0, *, a]
    #=> [0] length mismatch (given 1, expected 2+) (NoMatchingPatternError)

Ignore test failures of typeprof caused by this change for now.
---
 .github/workflows/ubuntu.yml       |   2 +-
 compile.c                          | 456 +++++++++++++++++++++++++++++--------
 defs/id.def                        |   1 +
 error.c                            |  75 +++++-
 include/ruby/internal/globals.h    |   1 +
 test/ruby/test_pattern_matching.rb | 127 +++++++++++
 vm.c                               |   7 +
 7 files changed, 572 insertions(+), 97 deletions(-)

diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml
index e148b76..f3ad645 100644
--- a/.github/workflows/ubuntu.yml
+++ b/.github/workflows/ubuntu.yml
@@ -59,7 +59,7 @@ jobs: https://github.com/ruby/ruby/blob/trunk/.github/workflows/ubuntu.yml#L59
         timeout-minutes: 30
         env:
           RUBY_TESTOPTS: "-q --tty=no"
-          TEST_BUNDLED_GEMS_ALLOW_FAILURES: ""
+          TEST_BUNDLED_GEMS_ALLOW_FAILURES: "typeprof"
       - uses: k0kubun/action-slack@v...
         with:
           payload: |
diff --git a/compile.c b/compile.c
index 6695a02..d73a42a 100644
--- a/compile.c
+++ b/compile.c
@@ -5939,12 +5939,22 @@ compile_case2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no https://github.com/ruby/ruby/blob/trunk/compile.c#L5939
     return COMPILE_OK;
 }
 
-static int iseq_compile_pattern_match(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *unmatched, int in_alt_pattern, int deconstructed_pos);
+static int iseq_compile_pattern_match(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *unmatched, bool in_single_pattern, bool in_alt_pattern, int base_index, bool use_deconstructed_cache);
 
-static int iseq_compile_array_deconstruct(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *deconstruct, LABEL *deconstructed, LABEL *match_failed, LABEL *type_error, int deconstructed_pos);
+static int iseq_compile_pattern_constant(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *match_failed, bool in_single_pattern, int base_index);
+static int iseq_compile_array_deconstruct(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *deconstruct, LABEL *deconstructed, LABEL *match_failed, LABEL *type_error, bool in_single_pattern, int base_index, bool use_deconstructed_cache);
+static int iseq_compile_pattern_set_general_errmsg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, VALUE errmsg, int base_index);
+static int iseq_compile_pattern_set_length_errmsg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, VALUE errmsg, VALUE pattern_length, int base_index);
+static int iseq_compile_pattern_set_eqq_errmsg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int base_index);
+
+#define CASE3_BI_OFFSET_DECONSTRUCTED_CACHE 0
+#define CASE3_BI_OFFSET_ERROR_STRING        1
+#define CASE3_BI_OFFSET_KEY_ERROR_P         2
+#define CASE3_BI_OFFSET_KEY_ERROR_MATCHEE   3
+#define CASE3_BI_OFFSET_KEY_ERROR_KEY       4
 
 static int
-iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *matched, LABEL *unmatched, int in_alt_pattern, int deconstructed_pos)
+iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *matched, LABEL *unmatched, bool in_single_pattern, bool in_alt_pattern, int base_index, bool use_deconstructed_cache)
 {
     const int line = nd_line(node);
     const NODE *line_node = node;
@@ -6022,31 +6032,32 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c https://github.com/ruby/ruby/blob/trunk/compile.c#L6032
         if (use_rest_num) {
             ADD_INSN1(ret, line_node, putobject, INT2FIX(0)); /* allocate stack for rest_num */
             ADD_INSN(ret, line_node, swap);
-            if (deconstructed_pos) {
-                deconstructed_pos++;
+            if (base_index) {
+                base_index++;
             }
         }
 
-        if (node->nd_pconst) {
-            ADD_INSN(ret, line_node, dup);
-            CHECK(COMPILE(ret, "constant", node->nd_pconst));
-            ADD_INSN1(ret, line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE));
-            ADD_INSNL(ret, line_node, branchunless, match_failed);
-        }
+        CHECK(iseq_compile_pattern_constant(iseq, ret, node, match_failed, in_single_pattern, base_index));
 
-        CHECK(iseq_compile_array_deconstruct(iseq, ret, node, deconstruct, deconstructed, match_failed, type_error, deconstructed_pos));
+        CHECK(iseq_compile_array_deconstruct(iseq, ret, node, deconstruct, deconstructed, match_failed, type_error, in_single_pattern, base_index, use_deconstructed_cache));
 
         ADD_INSN(ret, line_node, dup);
         ADD_SEND(ret, line_node, idLength, INT2FIX(0));
         ADD_INSN1(ret, line_node, putobject, INT2FIX(min_argc));
-        ADD_SEND(ret, line_node, apinfo->rest_arg ? idGE : idEq, INT2FIX(1));
+        ADD_SEND(ret, line_node, apinfo->rest_arg ? idGE : idEq, INT2FIX(1)); // (1)
+        if (in_single_pattern) {
+            CHECK(iseq_compile_pattern_set_length_errmsg(iseq, ret, node,
+                                                         apinfo->rest_arg ? rb_fstring_lit("%p length mismatch (given %p, expected %p+)") :
+                                                                            rb_fstring_lit("%p length mismatch (given %p, expected %p)"),
+                                                         INT2FIX(min_argc), base_index + 1 /* (1) */));
+        }
         ADD_INSNL(ret, line_node, branchunless, match_failed);
 
         for (i = 0; i < pre_args_num; i++) {
             ADD_INSN(ret, line_node, dup);
             ADD_INSN1(ret, line_node, putobject, INT2FIX(i));
-            ADD_SEND(ret, line_node, idAREF, INT2FIX(1));
-            CHECK(iseq_compile_pattern_match(iseq, ret, args->nd_head, match_failed, in_alt_pattern, FALSE));
+            ADD_SEND(ret, line_node, idAREF, INT2FIX(1)); // (2)
+            CHECK(iseq_compile_pattern_match(iseq, ret, args->nd_head, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (2) */, false));
             args = args->nd_next;
         }
 
@@ -6059,9 +6070,9 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c https://github.com/ruby/ruby/blob/trunk/compile.c#L6070
                 ADD_INSN1(ret, line_node, putobject, INT2FIX(min_argc));
                 ADD_SEND(ret, line_node, idMINUS, INT2FIX(1));
                 ADD_INSN1(ret, line_node, setn, INT2FIX(4));
-                ADD_SEND(ret, line_node, idAREF, INT2FIX(2));
+                ADD_SEND(ret, line_node, idAREF, INT2FIX(2)); // (3)
 
-                CHECK(iseq_compile_pattern_match(iseq, ret, apinfo->rest_arg, match_failed, in_alt_pattern, FALSE));
+                CHECK(iseq_compile_pattern_match(iseq, ret, apinfo->rest_arg, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (3) */, false));
             }
             else {
                 if (post_args_num > 0) {
@@ -6083,8 +6094,8 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c https://github.com/ruby/ruby/blob/trunk/compile.c#L6094
             ADD_INSN1(ret, line_node, topn, INT2FIX(3));
             ADD_SEND(ret, line_node, idPLUS, INT2FIX(1));
 
-            ADD_SEND(ret, line_node, idAREF, INT2FIX(1));
-            CHECK(iseq_compile_pattern_match(iseq, ret, args->nd_head, match_failed, in_alt_pattern, FALSE));
+            ADD_SEND(ret, line_node, idAREF, INT2FIX(1)); // (4)
+            CHECK(iseq_compile_pattern_match(iseq, ret, args->nd_head, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (4) */, false));
             args = args->nd_next;
         }
 
@@ -6173,19 +6184,17 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c https://github.com/ruby/ruby/blob/trunk/compile.c#L6184
         deconstruct = NEW_LABEL(line);
         deconstructed = NEW_LABEL(line);
 
-        if (node->nd_pconst) {
-            ADD_INSN(ret, line_node, dup);
-            CHECK(COMPILE(ret, "constant", node->nd_pconst));
-            ADD_INSN1(ret, line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE));
-            ADD_INSNL(ret, line_node, branchunless, match_failed);
-        }
+        CHECK(iseq_compile_pattern_constant(iseq, ret, node, match_failed, in_single_pattern, base_index));
 
-        CHECK(iseq_compile_array_deconstruct(iseq, ret, node, deconstruct, deconstructed, match_failed, type_error, deconstructed_pos));
+        CHECK(iseq_compile_array_deconstruct(iseq, ret, node, deconstruct, deconstructed, match_failed, type_error, in_single_pattern, base_index, use_deconstructed_cache));
 
         ADD_INSN(ret, line_node, dup);
         ADD_SEND(ret, line_node, idLength, INT2FIX(0));
         ADD_INSN1(ret, line_node, putobject, INT2FIX(args_num));
-        ADD_SEND(ret, line_node, idGE, INT2FIX(1));
+        ADD_SEND(ret, line_node, idGE, INT2FIX(1)); // (1)
+        if (in_single_pattern) {
+            CHECK(iseq_compile_pattern_set_length_errmsg(iseq, ret, node, rb_fstring_lit("%p length mismatch (given %p, expected %p+)"), INT2FIX(args_num), base_index + 1 /* (1) */));
+        }
         ADD_INSNL(ret, line_node, branchunless, match_failed);
 
         {
@@ -6196,13 +6205,13 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c https://github.com/ruby/ruby/blob/trunk/compile.c#L6205
             int j;
 
             ADD_INSN(ret, line_node, dup); /* allocate stack for len */
-            ADD_SEND(ret, line_node, idLength, INT2FIX(0));
+            ADD_SEND(re (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]