diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,7 @@
+2024-07-07
+        * Version bump (3.20). (#522)
+        * Add support for struct field updates. (#520)
+
 2024-05-07
         * Version bump (3.19.1). (#512)
 
diff --git a/copilot-interpreter.cabal b/copilot-interpreter.cabal
--- a/copilot-interpreter.cabal
+++ b/copilot-interpreter.cabal
@@ -1,6 +1,6 @@
 cabal-version:       >=1.10
 name:                copilot-interpreter
-version:             3.19.1
+version:             3.20
 synopsis:            Interpreter for Copilot.
 description:
   Interpreter for Copilot.
@@ -44,7 +44,7 @@
     base       >= 4.9 && < 5,
     pretty     >= 1.0 && < 1.2,
 
-    copilot-core >= 3.19.1 && < 3.20
+    copilot-core >= 3.20 && < 3.21
 
   exposed-modules:
 
diff --git a/src/Copilot/Interpret/Eval.hs b/src/Copilot/Interpret/Eval.hs
--- a/src/Copilot/Interpret/Eval.hs
+++ b/src/Copilot/Interpret/Eval.hs
@@ -2,10 +2,11 @@
 
 -- | A tagless interpreter for Copilot specifications.
 
-{-# LANGUAGE BangPatterns       #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE GADTs              #-}
-{-# LANGUAGE Safe               #-}
+{-# LANGUAGE BangPatterns        #-}
+{-# LANGUAGE DeriveDataTypeable  #-}
+{-# LANGUAGE GADTs               #-}
+{-# LANGUAGE Safe                #-}
+{-# LANGUAGE ScopedTypeVariables #-}
 
 module Copilot.Interpret.Eval
   ( Env
@@ -17,8 +18,9 @@
 
 import Copilot.Core            (Expr (..), Field (..), Id, Name, Observer (..),
                                 Op1 (..), Op2 (..), Op3 (..), Spec, Stream (..),
-                                Trigger (..), Type (..), UExpr (..), arrayElems,
-                                specObservers, specStreams, specTriggers)
+                                Trigger (..), Type (..), UExpr (..), Value (..),
+                                arrayElems, specObservers, specStreams,
+                                specTriggers, updateField)
 import Copilot.Interpret.Error (badUsage)
 
 import           Prelude hiding (id)
@@ -243,6 +245,12 @@
   BwShiftL _ _ -> ( \ !a !b -> shiftL a $! fromIntegral b )
   BwShiftR _ _ -> ( \ !a !b -> shiftR a $! fromIntegral b )
   Index    _   -> \xs n -> (arrayElems xs) !! (fromIntegral n)
+
+  UpdateField (Struct _) ty (fieldAccessor :: a -> Field s b) ->
+    \stream fieldValue ->
+      let newField :: Field s b
+          newField = Field fieldValue
+      in updateField stream (Value ty newField)
 
 -- | Apply a function to two numbers, so long as the second one is
 -- not zero.
