diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/Elvis.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/Elvis.java index 64f1ec7ded3..c3ebc93ac21 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/Elvis.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/Elvis.java @@ -103,6 +103,12 @@ public class Elvis extends SpelNodeImpl { @Override public void generateCode(MethodVisitor mv, CodeFlow cf) { + // If both elements are literals and the expression was not previously + // evaluated in interpreted mode, we may get here without the exit descriptor + // having been computed, so we must ensure the exit descriptor has been + // computed before proceeding. + computeExitTypeDescriptor(); + Label elseTarget = new Label(); Label endOfIf = new Label(); diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/SpelCompilationCoverageTests.java b/spring-expression/src/test/java/org/springframework/expression/spel/SpelCompilationCoverageTests.java index 1d0727ec44d..0ecf23aca17 100644 --- a/spring-expression/src/test/java/org/springframework/expression/spel/SpelCompilationCoverageTests.java +++ b/spring-expression/src/test/java/org/springframework/expression/spel/SpelCompilationCoverageTests.java @@ -1470,6 +1470,23 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests { assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/String"); } + @Test + void elvisWithImmediateCompilation() { + expression = parser.parseExpression("'a' ?: 'b'"); + // Both literals, so we can compile immediately without having previously + // evaluated the expression. + assertCanCompile(expression); + assertThat(expression.getValue(String.class)).isEqualTo("a"); + assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/String"); + + expression = parser.parseExpression("null ?: 'a'"); + // Both literals, so we can compile immediately without having previously + // evaluated the expression. + assertCanCompile(expression); + assertThat(expression.getValue(String.class)).isEqualTo("a"); + assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object"); + } + @Test // gh-19758 void elvisMiscellaneous() { SpelParserConfiguration configuration = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, null);