diff --git a/src/core/expression/qgsexpressionfunction.cpp b/src/core/expression/qgsexpressionfunction.cpp
index f4ac989f3b8..2a592facd63 100644
--- a/src/core/expression/qgsexpressionfunction.cpp
+++ b/src/core/expression/qgsexpressionfunction.cpp
@@ -4302,20 +4302,17 @@ bool QgsWithVariableExpressionFunction::isStatic( const QgsExpressionNodeFunctio
   if ( args->count() < 3 )
     return false;
 
+  // We only need to check if the node evaluation is static, if both - name and value - are static.
   if ( args->at( 0 )->isStatic( parent, context ) && args->at( 1 )->isStatic( parent, context ) )
   {
     QVariant name = args->at( 0 )->eval( parent, context );
     QVariant value = args->at( 1 )->eval( parent, context );
 
-    QgsExpressionContextScope *scope = new QgsExpressionContextScope();
-    scope->setVariable( name.toString(), value );
-
-    QgsExpressionContext *updatedContext = const_cast<QgsExpressionContext *>( context );
-    updatedContext->appendScope( scope );
-
-    if ( args->at( 2 )->isStatic( parent, updatedContext ) )
+    // Temporarily append a new scope to provide the variable
+    appendTemporaryVariable( context, name.toString(), value );
+    if ( args->at( 2 )->isStatic( parent, context ) )
       isStatic = true;
-    delete updatedContext->popScope();
+    popTemporaryVariable( context );
   }
 
   return false;
@@ -4332,15 +4329,13 @@ QVariant QgsWithVariableExpressionFunction::run( QgsExpressionNode::NodeList *ar
   QVariant name = args->at( 0 )->eval( parent, context );
   QVariant value = args->at( 1 )->eval( parent, context );
 
-  QgsExpressionContextScope *scope = new QgsExpressionContextScope();
-  scope->setVariable( name.toString(), value );
-
   QgsExpressionContext *updatedContext = const_cast<QgsExpressionContext *>( context );
   if ( !context )
     updatedContext = new QgsExpressionContext();
-  updatedContext->appendScope( scope );
+
+  appendTemporaryVariable( updatedContext, name.toString(), value );
   result = args->at( 2 )->eval( parent, updatedContext );
-  delete updatedContext->popScope();
+  popTemporaryVariable( updatedContext );
   if ( !context )
     delete updatedContext;
 
@@ -4369,13 +4364,24 @@ bool QgsWithVariableExpressionFunction::prepare( const QgsExpressionNodeFunction
   QVariant name = args->at( 0 )->prepare( parent, context );
   QVariant value = args->at( 1 )->prepare( parent, context );
 
-  QgsExpressionContextScope *scope = new QgsExpressionContextScope();
-  scope->setVariable( name.toString(), value );
-
-  QgsExpressionContext *updatedContext = const_cast<QgsExpressionContext *>( context );
-  updatedContext->appendScope( scope );
-  args->at( 2 )->prepare( parent, updatedContext );
-  delete updatedContext->popScope();
+  appendTemporaryVariable( context, name.toString(), value );
+  args->at( 2 )->prepare( parent, context );
+  popTemporaryVariable( context );
 
   return true;
 }
+
+void QgsWithVariableExpressionFunction::popTemporaryVariable( const QgsExpressionContext *context ) const
+{
+  QgsExpressionContext *updatedContext = const_cast<QgsExpressionContext *>( context );
+  delete updatedContext->popScope();
+}
+
+void QgsWithVariableExpressionFunction::appendTemporaryVariable( const QgsExpressionContext *context, const QString &name, const QVariant &value ) const
+{
+  QgsExpressionContextScope *scope = new QgsExpressionContextScope();
+  scope->setVariable( name, value );
+
+  QgsExpressionContext *updatedContext = const_cast<QgsExpressionContext *>( context );
+  updatedContext->appendScope( scope );
+}
diff --git a/src/core/expression/qgsexpressionfunction.h b/src/core/expression/qgsexpressionfunction.h
index fc6b8f80876..4734cad60de 100644
--- a/src/core/expression/qgsexpressionfunction.h
+++ b/src/core/expression/qgsexpressionfunction.h
@@ -29,6 +29,7 @@
 class QgsExpressionNodeFunction;
 class QgsExpression;
 class QgsExpressionContext;
+class QgsExpressionContextScope;
 
 /** \ingroup core
   * A abstract base class for defining QgsExpression functions.
@@ -475,6 +476,18 @@ class QgsWithVariableExpressionFunction : public QgsExpressionFunction
     QVariant func( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent ) override;
 
     bool prepare( const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context ) const override;
+
+  private:
+
+    /**
+     * Append a scope with a single variable definition (``name``=``value``)
+     */
+    void appendTemporaryVariable( const QgsExpressionContext *context, const QString &name, const QVariant &value ) const;
+
+    /**
+     * Pop the temporary scope again
+     */
+    void popTemporaryVariable( const QgsExpressionContext *context ) const;
 };
 
 #endif