summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNobuyoshi Nakada <[email protected]>2024-07-13 12:59:58 +0900
committerKevin Newton <[email protected]>2024-07-17 14:06:11 -0400
commit644424941a771f471134c40204ecbb4589dc74f2 ()
tree300bb16f7b66df659117437c8371de9367a439bb
parent7993b88eeec79cce14b04c37f91b0adc3ee1e14f (diff)
[Bug #20457] [Prism] Remove redundant return flag
Notes: Merged: https://.com/ruby/ruby/pull/11163
-rw-r--r--prism/config.yml6
-rw-r--r--prism/prism.c111
-rw-r--r--prism_compile.c129
-rw-r--r--test/prism/result/redundant_return_test.rb73
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_defn_complex.txt2
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_return.txt2
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_9669.txt2
7 files changed, 59 insertions, 266 deletions
@@ -735,11 +735,6 @@ flags:
- name: FORCED_US_ASCII_ENCODING
comment: "internal bytes forced the encoding to US-ASCII"
comment: Flags for regular expression and match last line nodes.
- - name: ReturnNodeFlags
- values:
- - name: REDUNDANT
- comment: "a return statement that is redundant because it is the last statement in a method"
- comment: Flags for return nodes.
- name: ShareableConstantNodeFlags
values:
- name: LITERAL
@@ -3455,7 +3450,6 @@ nodes:
retry
^^^^^
- name: ReturnNode
- flags: ReturnNodeFlags
fields:
- name: keyword_loc
type: location
@@ -3796,113 +3796,6 @@ pm_def_node_receiver_check(pm_parser_t *parser, const pm_node_t *node) {
}
/**
- * When a method body is created, we want to check if the last statement is a
- * return or a statement that houses a return. If it is, then we want to mark
- * that return as being redundant so that we can compile it differently but also
- * so that we can indicate that to the user.
- */
-static void
-pm_def_node_body_redundant_return(pm_node_t *node) {
- switch (PM_NODE_TYPE(node)) {
- case PM_RETURN_NODE:
- node->flags |= PM_RETURN_NODE_FLAGS_REDUNDANT;
- break;
- case PM_BEGIN_NODE: {
- pm_begin_node_t *cast = (pm_begin_node_t *) node;
-
- if (cast->statements != NULL && cast->else_clause == NULL) {
- pm_def_node_body_redundant_return((pm_node_t *) cast->statements);
- }
- break;
- }
- case PM_STATEMENTS_NODE: {
- pm_statements_node_t *cast = (pm_statements_node_t *) node;
-
- if (cast->body.size > 0) {
- pm_def_node_body_redundant_return(cast->body.nodes[cast->body.size - 1]);
- }
- break;
- }
- case PM_IF_NODE: {
- pm_if_node_t *cast = (pm_if_node_t *) node;
-
- if (cast->statements != NULL) {
- pm_def_node_body_redundant_return((pm_node_t *) cast->statements);
- }
-
- if (cast->consequent != NULL) {
- pm_def_node_body_redundant_return(cast->consequent);
- }
- break;
- }
- case PM_UNLESS_NODE: {
- pm_unless_node_t *cast = (pm_unless_node_t *) node;
-
- if (cast->statements != NULL) {
- pm_def_node_body_redundant_return((pm_node_t *) cast->statements);
- }
-
- if (cast->consequent != NULL) {
- pm_def_node_body_redundant_return((pm_node_t *) cast->consequent);
- }
- break;
- }
- case PM_ELSE_NODE: {
- pm_else_node_t *cast = (pm_else_node_t *) node;
-
- if (cast->statements != NULL) {
- pm_def_node_body_redundant_return((pm_node_t *) cast->statements);
- }
- break;
- }
- case PM_CASE_NODE: {
- pm_case_node_t *cast = (pm_case_node_t *) node;
- pm_node_t *condition;
-
- PM_NODE_LIST_FOREACH(&cast->conditions, index, condition) {
- pm_def_node_body_redundant_return(condition);
- }
-
- if (cast->consequent != NULL) {
- pm_def_node_body_redundant_return((pm_node_t *) cast->consequent);
- }
- break;
- }
- case PM_WHEN_NODE: {
- pm_when_node_t *cast = (pm_when_node_t *) node;
-
- if (cast->statements != NULL) {
- pm_def_node_body_redundant_return((pm_node_t *) cast->statements);
- }
- break;
- }
- case PM_CASE_MATCH_NODE: {
- pm_case_match_node_t *cast = (pm_case_match_node_t *) node;
- pm_node_t *condition;
-
- PM_NODE_LIST_FOREACH(&cast->conditions, index, condition) {
- pm_def_node_body_redundant_return(condition);
- }
-
- if (cast->consequent != NULL) {
- pm_def_node_body_redundant_return((pm_node_t *) cast->consequent);
- }
- break;
- }
- case PM_IN_NODE: {
- pm_in_node_t *cast = (pm_in_node_t *) node;
-
- if (cast->statements != NULL) {
- pm_def_node_body_redundant_return((pm_node_t *) cast->statements);
- }
- break;
- }
- default:
- break;
- }
-}
-
-/**
* Allocate and initialize a new DefNode node.
*/
static pm_def_node_t *
@@ -3934,10 +3827,6 @@ pm_def_node_create(
pm_def_node_receiver_check(parser, receiver);
}
- if (body != NULL) {
- pm_def_node_body_redundant_return(body);
- }
-
*node = (pm_def_node_t) {
{
.type = PM_DEF_NODE,
@@ -5542,32 +5542,25 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
const pm_node_location_t location = PM_NODE_START_LOCATION(parser, node);
int lineno = (int) location.line;
- if (PM_NODE_TYPE_P(node, PM_RETURN_NODE) && PM_NODE_FLAG_P(node, PM_RETURN_NODE_FLAGS_REDUNDANT) && ((const pm_return_node_t *) node)->arguments == NULL) {
- // If the node that we're compiling is a return node that is redundant,
- // then it cannot be considered a line node because the other parser
- // eliminates it from the parse tree. In this case we must replicate
- // this behavior.
- } else {
- if (PM_NODE_TYPE_P(node, PM_BEGIN_NODE) && (((const pm_begin_node_t *) node)->statements == NULL) && (((const pm_begin_node_t *) node)->rescue_clause != NULL)) {
- // If this node is a begin node and it has empty statements and also
- // has a rescue clause, then the other parser considers it as
- // starting on the same line as the rescue, as opposed to the
- // location of the begin keyword. We replicate that behavior here.
- lineno = (int) PM_NODE_START_LINE_COLUMN(parser, ((const pm_begin_node_t *) node)->rescue_clause).line;
- }
- if (PM_NODE_FLAG_P(node, PM_NODE_FLAG_NEWLINE) && ISEQ_COMPILE_DATA(iseq)->last_line != lineno) {
- // If this node has the newline flag set and it is on a new line
- // from the previous nodes that have been compiled for this ISEQ,
- // then we need to emit a newline event.
- int event = RUBY_EVENT_LINE;
- ISEQ_COMPILE_DATA(iseq)->last_line = lineno;
- if (ISEQ_COVERAGE(iseq) && ISEQ_LINE_COVERAGE(iseq)) {
- event |= RUBY_EVENT_COVERAGE_LINE;
- }
- PUSH_TRACE(ret, event);
}
}
switch (PM_NODE_TYPE(node)) {
@@ -8367,63 +8360,53 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
const pm_return_node_t *cast = (const pm_return_node_t *) node;
const pm_arguments_node_t *arguments = cast->arguments;
- if (PM_NODE_FLAG_P(cast, PM_RETURN_NODE_FLAGS_REDUNDANT)) {
- if (arguments) {
- PM_COMPILE_NOT_POPPED((const pm_node_t *) arguments);
- }
- else {
- PUSH_INSN(ret, location, putnil);
- }
}
- else {
- enum rb_iseq_type type = ISEQ_BODY(iseq)->type;
- LABEL *splabel = 0;
- const rb_iseq_t *parent_iseq = iseq;
- enum rb_iseq_type parent_type = ISEQ_BODY(parent_iseq)->type;
- while (parent_type == ISEQ_TYPE_RESCUE || parent_type == ISEQ_TYPE_ENSURE) {
- if (!(parent_iseq = ISEQ_BODY(parent_iseq)->parent_iseq)) break;
- parent_type = ISEQ_BODY(parent_iseq)->type;
}
-
- switch (parent_type) {
- case ISEQ_TYPE_TOP:
- case ISEQ_TYPE_MAIN:
- if (arguments) {
- rb_warn("argument of top-level return is ignored");
- }
- if (parent_iseq == iseq) {
- type = ISEQ_TYPE_METHOD;
- }
- break;
- default:
- break;
}
- if (type == ISEQ_TYPE_METHOD) {
- splabel = NEW_LABEL(0);
- PUSH_LABEL(ret, splabel);
- PUSH_ADJUST(ret, location, 0);
- }
- if (arguments) {
- PM_COMPILE_NOT_POPPED((const pm_node_t *) arguments);
- }
- else {
- PUSH_INSN(ret, location, putnil);
- }
- if (type == ISEQ_TYPE_METHOD && can_add_ensure_iseq(iseq)) {
- pm_add_ensure_iseq(ret, iseq, 1, scope_node);
- PUSH_TRACE(ret, RUBY_EVENT_RETURN);
- PUSH_INSN(ret, location, leave);
- PUSH_ADJUST_RESTORE(ret, splabel);
- if (!popped) PUSH_INSN(ret, location, putnil);
- }
- else {
- PUSH_INSN1(ret, location, throw, INT2FIX(TAG_RETURN));
- if (popped) PUSH_INSN(ret, location, pop);
- }
}
return;
@@ -1,73 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "../test_helper"
-
-module Prism
- class RedundantReturnTest < TestCase
- def test_statements
- assert_redundant_return("def foo; return; end")
- refute_redundant_return("def foo; return; 1; end")
- end
-
- def test_begin_implicit
- assert_redundant_return("def foo; return; rescue; end")
- refute_redundant_return("def foo; return; 1; rescue; end")
- refute_redundant_return("def foo; return; rescue; else; end")
- end
-
- def test_begin_explicit
- assert_redundant_return("def foo; begin; return; rescue; end; end")
- refute_redundant_return("def foo; begin; return; 1; rescue; end; end")
- refute_redundant_return("def foo; begin; return; rescue; else; end; end")
- end
-
- def test_if
- assert_redundant_return("def foo; return if bar; end")
- end
-
- def test_unless
- assert_redundant_return("def foo; return unless bar; end")
- end
-
- def test_else
- assert_redundant_return("def foo; if bar; baz; else; return; end; end")
- end
-
- def test_case_when
- assert_redundant_return("def foo; case bar; when baz; return; end; end")
- end
-
- def test_case_else
- assert_redundant_return("def foo; case bar; when baz; else; return; end; end")
- end
-
- def test_case_match_in
- assert_redundant_return("def foo; case bar; in baz; return; end; end")
- end
-
- def test_case_match_else
- assert_redundant_return("def foo; case bar; in baz; else; return; end; end")
- end
-
- private
-
- def assert_redundant_return(source)
- assert find_return(source).redundant?
- end
-
- def refute_redundant_return(source)
- refute find_return(source).redundant?
- end
-
- def find_return(source)
- queue = [Prism.parse(source).value]
-
- while (current = queue.shift)
- return current if current.is_a?(ReturnNode)
- queue.concat(current.compact_child_nodes)
- end
-
- flunk "Could not find return node in #{node.inspect}"
- end
- end
-end
@@ -56,7 +56,7 @@
│ │ ├── binary_operator: :*
│ │ └── depth: 0
│ └── @ ReturnNode (location: (4,2)-(4,10))
- │ ├── flags: newline, redundant
│ ├── keyword_loc: (4,2)-(4,8) = "return"
│ └── arguments:
│ @ ArgumentsNode (location: (4,9)-(4,10))
@@ -27,7 +27,7 @@
│ │ ├── flags: ∅
│ │ └── body: (length: 1)
│ │ └── @ ReturnNode (location: (3,10)-(3,19))
- │ │ ├── flags: newline, redundant
│ │ ├── keyword_loc: (3,10)-(3,16) = "return"
│ │ └── arguments:
│ │ @ ArgumentsNode (location: (3,17)-(3,19))
@@ -29,7 +29,7 @@
│ │ ├── flags: ∅
│ │ └── body: (length: 1)
│ │ └── @ ReturnNode (location: (2,0)-(2,6))
- │ │ ├── flags: newline, redundant
│ │ ├── keyword_loc: (2,0)-(2,6) = "return"
│ │ └── arguments: ∅
│ ├── locals: [:b]