diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index ebc62034d2..4178cde3b2 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -5699,16 +5699,6 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
 											   table_slot_callbacks(oldrel));
 			newslot = MakeSingleTupleTableSlot(newTupDesc,
 											   table_slot_callbacks(newrel));
-
-			/*
-			 * Set all columns in the new slot to NULL initially, to ensure
-			 * columns added as part of the rewrite are initialized to NULL.
-			 * That is necessary as tab->newvals will not contain an
-			 * expression for columns with a NULL default, e.g. when adding a
-			 * column without a default together with a column with a default
-			 * requiring an actual rewrite.
-			 */
-			ExecStoreAllNullTuple(newslot);
 		}
 		else
 		{
@@ -5747,9 +5737,21 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
 
 			if (tab->rewrite > 0)
 			{
+				/*
+				 * Set all columns in the new slot to NULL initially, to
+				 * ensure columns added as part of the rewrite are initialized
+				 * to NULL.  That is necessary as tab->newvals will not
+				 * contain an expression for columns with a NULL default, e.g.
+				 * when adding a column without a default together with a
+				 * column with a default requiring an actual rewrite.
+				 * Moreover, we must do it each time through, so that the slot
+				 * contents are sane in case any generated expression contains
+				 * a whole-row Var (which will read this same slot).
+				 */
+				ExecStoreAllNullTuple(newslot);
+
 				/* Extract data from old tuple */
 				slot_getallattrs(oldslot);
-				ExecClearTuple(newslot);
 
 				/* copy attributes */
 				memcpy(newslot->tts_values, oldslot->tts_values,
@@ -5782,12 +5784,12 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
 									   &newslot->tts_isnull[ex->attnum - 1]);
 				}
 
-				ExecStoreVirtualTuple(newslot);
-
 				/*
 				 * Now, evaluate any expressions whose inputs come from the
 				 * new tuple.  We assume these columns won't reference each
-				 * other, so that there's no ordering dependency.
+				 * other, so that there's no ordering dependency.  However,
+				 * because we allow whole-row references in GENERATED
+				 * expressions, that's not strictly true ...
 				 */
 				econtext->ecxt_scantuple = newslot;
 
