Skip to content

Commit 056951a

Browse files
committed
Replace ArrayCastNode by SplatCastNode and ArrayConvertNode
* ArrayCastNode did not handle all values and had outdated logic. * Fixes #2355
1 parent d8c88f0 commit 056951a

File tree

4 files changed

+27
-142
lines changed

4 files changed

+27
-142
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Bug fixes:
1010
* `Truffle::POSIX.select` was being redefined repeatedly (#2332).
1111
* Fix the `--backtraces-raise` and `--backtraces-rescue` options in JVM mode (#2335).
1212
* Fix `File.{atime, mtime, ctime}` to include nanoseconds (#2337).
13+
* Fix `Array#[a, b] = "frozen string literal".freeze` (#2355).
1314

1415
Compatibility:
1516

src/main/java/org/truffleruby/core/array/ArrayConvertNode.java

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,34 @@
99
*/
1010
package org.truffleruby.core.array;
1111

12+
import com.oracle.truffle.api.dsl.Cached;
13+
import com.oracle.truffle.api.dsl.Specialization;
1214
import com.oracle.truffle.api.profiles.ConditionProfile;
13-
import org.truffleruby.core.cast.ArrayCastNode;
1415
import org.truffleruby.language.RubyContextNode;
16+
import org.truffleruby.language.dispatch.DispatchNode;
1517

16-
/** Attempts converting its argument to an array, via {@link ArrayCastNode} (i.e. calling "to_ary"), or if that doesn't
17-
* work, by wrapping it inside a one-element array. */
18-
public final class ArrayConvertNode extends RubyContextNode {
18+
/** Attempts converting its argument to an array by calling #to_ary, or if that doesn't work, by wrapping it inside a
19+
* one-element array. */
20+
public abstract class ArrayConvertNode extends RubyContextNode {
1921

20-
@Child ArrayCastNode arrayCast = ArrayCastNode.create();
21-
@Child ArrayBuilderNode arrayBuilder = ArrayBuilderNode.create();
22-
private final ConditionProfile cantCast = ConditionProfile.create();
22+
public abstract RubyArray execute(Object value);
2323

24-
public static ArrayConvertNode create() {
25-
return new ArrayConvertNode();
24+
@Specialization
25+
protected RubyArray castArray(RubyArray array) {
26+
return array;
2627
}
2728

28-
public RubyArray execute(Object object) {
29-
Object converted = arrayCast.execute(object);
30-
if (cantCast.profile(converted == nil)) {
29+
@Specialization(guards = "!isRubyArray(object)")
30+
protected RubyArray cast(Object object,
31+
@Cached ConditionProfile canCast,
32+
@Cached ArrayBuilderNode arrayBuilder,
33+
@Cached(parameters = "PRIVATE_RETURN_MISSING") DispatchNode toArrayNode) {
34+
final Object result = toArrayNode.call(object, "to_ary");
35+
if (canCast.profile(result instanceof RubyArray)) {
36+
return (RubyArray) result;
37+
} else {
3138
return ArrayHelpers.specializedRubyArrayOf(getContext(), getLanguage(), arrayBuilder, object);
3239
}
33-
return (RubyArray) converted;
3440
}
41+
3542
}

src/main/java/org/truffleruby/core/cast/ArrayCastNode.java

Lines changed: 0 additions & 127 deletions
This file was deleted.

src/main/java/org/truffleruby/parser/MethodTranslator.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
import org.truffleruby.RubyLanguage;
1616
import org.truffleruby.collections.CachedSupplier;
1717
import org.truffleruby.core.IsNilNode;
18-
import org.truffleruby.core.cast.ArrayCastNodeGen;
18+
import org.truffleruby.core.cast.SplatCastNode;
19+
import org.truffleruby.core.cast.SplatCastNode.NilBehavior;
20+
import org.truffleruby.core.cast.SplatCastNodeGen;
1921
import org.truffleruby.core.proc.ProcCallTargets;
2022
import org.truffleruby.core.proc.ProcType;
2123
import org.truffleruby.language.RubyLambdaRootNode;
@@ -201,7 +203,9 @@ private RubyNode preludeProc(
201203
final RubyNode readArrayNode = profileArgument(
202204
language,
203205
new ReadPreArgumentNode(0, MissingArgumentBehavior.RUNTIME_ERROR));
204-
final RubyNode castArrayNode = ArrayCastNodeGen.create(readArrayNode);
206+
final SplatCastNode castArrayNode = SplatCastNodeGen
207+
.create(language, NilBehavior.NIL, true, readArrayNode);
208+
castArrayNode.doNotCopy();
205209

206210
final FrameSlot arraySlot = environment.declareVar(environment.allocateLocalTemp("destructure"));
207211
final RubyNode writeArrayNode = new WriteLocalVariableNode(arraySlot, castArrayNode);

0 commit comments

Comments
 (0)