Skip to content

Commit

Permalink
Kernel#lambda raises when given non-lambda, non-literal block
Browse files Browse the repository at this point in the history
  • Loading branch information
Th3-M4jor committed Dec 30, 2024
1 parent c229bfd commit 7ab9472
Show file tree
Hide file tree
Showing 3 changed files with 8 additions and 14 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Compatibility:
* Support `symbolize_names` argument to `MatchData#named_captures` (#3681, @rwstauner).
* Support `Proc#initialize_{dup,copy}` for subclasses (#3681, @rwstauner).
* Remove deprecated `Encoding#replicate` method (#3681, @rwstauner).
* `Kernel#lambda` with now raises `ArgumentError` when given a non-lambda, non-literal block (#3681, @Th3-M4jor).

Performance:

Expand Down
1 change: 0 additions & 1 deletion spec/tags/core/kernel/lambda_tags.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
fails:Kernel.lambda creates a lambda-style Proc when called with zsuper
fails:Kernel.lambda does not create lambda-style Procs when captured with #method
fails:Kernel.lambda when called without a literal block raises when proc isn't a lambda
20 changes: 7 additions & 13 deletions src/main/java/org/truffleruby/core/kernel/KernelNodes.java
Original file line number Diff line number Diff line change
Expand Up @@ -1148,23 +1148,17 @@ RubyProc lambdaFromProcBlock(RubyProc block) {
return ProcOperations.createLambdaFromBlock(getContext(), getLanguage(), block);
}

@Specialization(guards = { "!isLiteralBlock(block)", "block.isProc()" })
RubyProc lambdaFromExistingProc(RubyProc block,
@Cached WarnNode warnNode) {
if (warnNode.shouldWarnForDeprecation()) {
warnNode.warningMessage(
getContext().getCallStack().getTopMostUserSourceSection(),
"lambda without a literal block is deprecated; use the proc without lambda instead");
}

// If the argument isn't a literal, its original behaviour (proc or lambda) is preserved.
@Specialization(guards = { "!isLiteralBlock(block)", "block.isLambda()" })
RubyProc lambdaFromExistingLambda(RubyProc block) {
// If the argument isn't a literal, its original behaviour is preserved only if its a lambda.
return block;
}

@Specialization(guards = { "!isLiteralBlock(block)", "block.isLambda()" })
@Specialization(guards = { "!isLiteralBlock(block)", "block.isProc()" })
RubyProc lambdaFromExistingProc(RubyProc block) {
// If the argument isn't a literal, its original behaviour (proc or lambda) is preserved.
return block;
throw new RaiseException(
getContext(),
coreExceptions().argumentError("the lambda method requires a literal block", this));
}

@TruffleBoundary
Expand Down

0 comments on commit 7ab9472

Please sign in to comment.