diff --git a/CHANGES.md b/CHANGES.md
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,6 +1,16 @@
 `th-desugar` release notes
 ==========================
 
+Version 1.5.5
+-------------
+
+* Fix issue #34. This means that desugaring (twice) is idempotent over
+expressions, after the second time. That is, if you desugar an expression,
+sweeten it, desugar again, sweeten again, and then desugar a third time, you
+get the same result as when you desugared the second time. (The extra
+round-trip is necessary there to make the output smaller in certain common
+cases.)
+
 Version 1.5.4.1
 ---------------
 * Fix issue #32, concerning reification of classes with default methods.
diff --git a/Language/Haskell/TH/Desugar/Core.hs b/Language/Haskell/TH/Desugar/Core.hs
--- a/Language/Haskell/TH/Desugar/Core.hs
+++ b/Language/Haskell/TH/Desugar/Core.hs
@@ -226,6 +226,11 @@
   let failure = DAppE (DVarE 'error) (DLitE (StringL "Non-exhaustive guards in multi-way if")) in
   dsGuards guarded_exps failure
 dsExp (LetE decs exp) = DLetE <$> dsLetDecs decs <*> dsExp exp
+    -- the following special case avoids creating a new "let" when it's not
+    -- necessary. See #34.
+dsExp (CaseE (VarE scrutinee) matches) = do
+  matches' <- dsMatches scrutinee matches
+  return $ DCaseE (DVarE scrutinee) matches'
 dsExp (CaseE exp matches) = do
   scrutinee <- newUniqueName "scrutinee"
   exp' <- dsExp exp
@@ -285,7 +290,7 @@
     extract_type_name (SigT t _) = extract_type_name t
     extract_type_name (ConT n) = return n
     extract_type_name _ = impossible "Record selector domain not a datatype."
-    
+
     filter_cons_with_names cons field_names =
       filter has_names cons
       where
@@ -600,7 +605,7 @@
 remove_arrows n (DArrowK _ k) = remove_arrows (n-1) k
 remove_arrows _ _ =
   impossible "Internal error: Fix for bug 8884 ran out of arrows."
-  
+
 #else
 fixBug8884ForFamilies dec = return (dec, 0)   -- return value ignored
 #endif
@@ -671,7 +676,7 @@
 dsDec (DefaultSigD n ty) = (:[]) <$> (DDefaultSigD n <$> dsType ty)
 #endif
 
-  
+
 -- | Desugar @Dec@s that can appear in a let expression
 dsLetDecs :: DsMonad q => [Dec] -> q [DLetDec]
 dsLetDecs = concatMapM dsLetDec
@@ -750,7 +755,7 @@
           -> q [DClause]
 dsClauses _ [] = return []
 dsClauses n (Clause pats (NormalB exp) where_decs : rest) = do
-  -- this is just a convenience optimization; we could tuple up all the patterns
+  -- this case is necessary to maintain the roundtrip property.
   rest' <- dsClauses n rest
   exp' <- dsExp exp
   where_decs' <- dsLetDecs where_decs
@@ -895,7 +900,7 @@
 -- available.
 dsReify :: DsMonad q => Name -> q (Maybe DInfo)
 dsReify = traverse dsInfo <=< reifyWithLocals_maybe
-  
+
 -- create a list of expressions in the same order as the fields in the first argument
 -- but with the values as given in the second argument
 -- if a field is missing from the second argument, use the corresponding expression
diff --git a/Test/Run.hs b/Test/Run.hs
--- a/Test/Run.hs
+++ b/Test/Run.hs
@@ -222,6 +222,16 @@
                     exps (map sweeten sexps)
                   return $ ListE bools )
 
+test_roundtrip :: [Bool]
+test_roundtrip = $( do exprs <- sequence test_exprs
+                       ds_exprs1 <- mapM dsExp exprs
+                       let th_exprs1 = map expToTH ds_exprs1
+                       ds_exprs2 <- mapM dsExp th_exprs1
+                       let th_exprs2 = map expToTH ds_exprs2
+                       ds_exprs3 <- mapM dsExp th_exprs2
+                       let bools = zipWith eqTH ds_exprs2 ds_exprs3
+                       Syn.lift bools )
+
 main :: IO ()
 main = hspec $ do
   describe "th-desugar library" $ do
@@ -261,5 +271,7 @@
       local_reifications normal_reifications [1..]
 
     zipWithM (\b n -> it ("works on simplCase test " ++ show n) b) simplCase [1..]
+
+    zipWithM (\b n -> it ("round-trip successfully on case " ++ show n) b) test_roundtrip [1..]
 
     fromHUnitTest tests
diff --git a/Test/Splices.hs b/Test/Splices.hs
--- a/Test/Splices.hs
+++ b/Test/Splices.hs
@@ -385,3 +385,46 @@
     [ [t|forall a. a ~ Int => a|]
     , [t|forall a. [a]|]
     , [t|forall a b. (a,b)|] ]
+
+test_exprs :: [Q Exp]
+test_exprs = [ test1_sections
+             , test2_lampats
+             , test3_lamcase
+-- see above             , test4_tuples
+             , test5_ifs
+             , test6_ifs2
+             , test7_let
+             , test8_case
+             , test9_do
+             , test10_comp
+#if __GLASGOW_HASKELL__ >= 707
+             , test11_parcomp
+             , test12_parcomp2
+#endif
+             , test13_sig
+             , test14_record
+             , test15_litp
+             , test16_tupp
+             , test17_infixp
+             , test18_tildep
+             , test19_bangp
+             , test20_asp
+             , test21_wildp
+             , test22_listp
+             , test24_fun
+             , test25_fun2
+             , test26_forall
+             , test27_kisig
+             , test28_tupt
+             , test29_listt
+             , test30_promoted
+             , test31_constraint
+             , test32_tylit
+             , test33_tvbs
+             , test34_let_as
+#if __GLASGOW_HASKELL__ >= 709
+             , test37_pred
+             , test38_pred2
+             , test39_eq
+#endif
+             ]
diff --git a/th-desugar.cabal b/th-desugar.cabal
--- a/th-desugar.cabal
+++ b/th-desugar.cabal
@@ -1,5 +1,5 @@
 name:           th-desugar
-version:        1.5.4.1
+version:        1.5.5
 cabal-version:  >= 1.10
 synopsis:       Functions to desugar Template Haskell
 homepage:       http://www.cis.upenn.edu/~eir/packages/th-desugar
@@ -26,7 +26,7 @@
 source-repository this
   type:     git
   location: https://github.com/goldfirere/th-desugar.git
-  tag:      v1.5.4.1
+  tag:      v1.5.5
 
 library
   build-depends:
