diff --git a/CHANGES.txt b/CHANGES.txt
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,5 +1,7 @@
 Changelog for record-dot-preprocessor
 
+0.2.2, released 2019-12-08
+    #26, make a {b=c} not desugar to setField
 0.2.1, released 2019-11-02
     #25, support promoted data kinds, e.g. 'Int
     #12, support more things around GADTs
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # record-dot-preprocessor [![Hackage version](https://img.shields.io/hackage/v/record-dot-preprocessor.svg?label=Hackage)](https://hackage.haskell.org/package/record-dot-preprocessor) [![Stackage version](https://www.stackage.org/package/record-dot-preprocessor/badge/nightly?label=Stackage)](https://www.stackage.org/package/record-dot-preprocessor) [![Build status](https://img.shields.io/travis/ndmitchell/record-dot-preprocessor/master.svg?label=Build)](https://travis-ci.org/ndmitchell/record-dot-preprocessor)
 
-In almost every programming language `a.b` will get the `b` field from the `a` data type, and many different data types can have a `b` field. The reason this feature is ubiquitous is because it's _useful_. The `record-dot-preprocessor` brings this feature to Haskell. Some examples:
+In almost every programming language `a.b` will get the `b` field from the `a` data type, and many different data types can have a `b` field. The reason this feature is ubiquitous is because it's _useful_. This feature has been [proposed for Haskell](https://github.com/ghc-proposals/ghc-proposals/pull/282) as `RecordDotSyntax`. The `record-dot-preprocessor` brings this feature to Haskell today. Some examples:
 
 ```haskell
 data Company = Company {name :: String, owner :: Person}
@@ -31,7 +31,7 @@
 Using the preprocessor or the GHC plugin you can write:
 
 * `expr.lbl` is equivalent to `getField @"lbl" expr` (the `.` cannot have whitespace on either side).
-* `expr{lbl = val}` is equivalent to `setField @"lbl" expr val`.
+* `expr{lbl = val}` is equivalent to `setField @"lbl" expr val` (the `{` cannot have whitespace before it).
 * `(.lbl)` is equivalent to `(\x -> x.lbl)` (the `.` cannot have whitespace after).
 
 Using the preprocessor, but _not_ the GHC plugin:
@@ -52,3 +52,7 @@
 ## How does this magic compare to other magic?
 
 Records in Haskell are well known to be [pretty lousy](https://www.yesodweb.com/blog/2011/09/limitations-of-haskell). There are [many proposals](https://wiki.haskell.org/Extensible_record) that aim to make Haskell records more powerful using dark arts taken from type systems and category theory. This preprocessor aims for simplicity - combining existing elements into a coherent story. The aim is to do no worse than Java, not achieve perfection.
+
+## Any advice for using this magic?
+
+The most important consideration is that all records used by `a.b` or `a{b=c}` syntax _must_ have `HasField` instances, which requires either running the preprocessor/plugin over the module defining them, or writing orphan instances by hand. To use records which don't have such instances use normal selector functions (e.g. `b a`) and insert a space before the `{` (e.g. `a {b=c}`).
diff --git a/examples/Both.hs b/examples/Both.hs
--- a/examples/Both.hs
+++ b/examples/Both.hs
@@ -4,9 +4,10 @@
 {-# LANGUAGE PartialTypeSignatures, GADTs, StandaloneDeriving, DataKinds #-} -- also tests we put language extensions before imports
 
 import Control.Exception
+import Data.Version
 
 main :: IO ()
-main = test1 >> test2 >> test3 >> test4 >> putStrLn "All worked"
+main = test1 >> test2 >> test3 >> test4 >> test5 >> putStrLn "All worked"
 
 (===) :: (Show a, Eq a) => a -> a -> IO ()
 a === b = if a == b then return () else fail $ "Mismatch, " ++ show a ++ " /= " ++ show b
@@ -43,8 +44,8 @@
     (foo2.foo1)._2 === 2
 
     -- test expr{lbl = val}
-    foo {foo1 = "a"} === Foo "a" 2
-    foo {foo1 = "a", foo1 = "b"} === foo{foo1 = "b"}
+    foo{foo1 = "a"} === Foo "a" 2
+    foo{foo1 = "a", foo1 = "b"} === foo{foo1 = "b"}
     null (foo{foo1 = []}.foo1) === True
     foo{foo1 = "a"}.foo1 === "a"
     let _foo2 = 8 in foo{_foo2} === Foo "test" 8
@@ -142,11 +143,21 @@
   f7 [AA 1, AA 2, AA 3] === [1, 2, 3]
   f8 [BB (AA 1) (AA 2), BB (AA 2) (AA 3), BB (AA 3) (AA 4)] === [1, 2, 3]
   where
-    f1 :: CC -> Int -> Int -> CC; f1 s t u = s {aa = t, bb = u}
-    f2 :: CC -> Int -> Int -> CC; f2 s t u = s {aa = t + u}
-    f3 :: AA -> AA; f3 s = s {xx = s.xx + 1}
-    f4 :: BB -> BB; f4 s = s {yy = s.yy, zz = s.zz{xx = 4}}
-    f5 :: BB -> BB; f5 s = s {yy = s.yy, zz = s.zz{xx = (\ x -> x * x) s.zz.xx}}
+    f1 :: CC -> Int -> Int -> CC; f1 s t u = s{aa = t, bb = u}
+    f2 :: CC -> Int -> Int -> CC; f2 s t u = s{aa = t + u}
+    f3 :: AA -> AA; f3 s = s{xx = s.xx + 1}
+    f4 :: BB -> BB; f4 s = s{yy = s.yy, zz = s.zz{xx = 4}}
+    f5 :: BB -> BB; f5 s = s{yy = s.yy, zz = s.zz{xx = (\ x -> x * x) s.zz.xx}}
     f6 :: BB -> BB; f6 s = s{yy = s.yy{xx = s.yy.xx + 1}, zz = s.zz{xx = (\ x -> x * x) s.zz{xx = s.zz.xx}.xx}}
     f7 :: [AA] -> [Int]; f7 l = map (.xx) l
     f8 :: [BB] -> [Int]; f8 l = map (.yy.xx) l
+
+-- ---------------------------------------------------------------------
+-- Test we can still non-instance fields
+
+test5 :: IO ()
+test5 = do
+    let v = makeVersion [1,2,3]
+    versionBranch v === [1,2,3]
+    -- the space before the { stops it from using record update
+    showVersion (v {versionBranch=[1]}) === "1"
diff --git a/plugin/RecordDotPreprocessor.hs b/plugin/RecordDotPreprocessor.hs
--- a/plugin/RecordDotPreprocessor.hs
+++ b/plugin/RecordDotPreprocessor.hs
@@ -139,7 +139,7 @@
     , (rhsApp, rhs) <- getAppLHS rhs
     , (rhsRec, rhs) <- getRec rhs
     , Just sel <- getSelector rhs
-    = onExp $ lhsOp $ rhsApp $ lhsApp $ rhsRec $ mkParen $ setL o $ mkVar var_getField `mkAppType` sel `mkApp` lhs
+    = onExp $ setL o $ lhsOp $ rhsApp $ lhsApp $ rhsRec $ mkParen $ mkVar var_getField `mkAppType` sel `mkApp` lhs
 
 -- Turn (.foo.bar) into getField calls
 onExp (L o (SectionR _ mid@(isDot -> True) rhs))
@@ -152,11 +152,16 @@
     = setL o $ foldl1 (\x y -> noL $ OpApp noE x (mkVar var_dot) y) $ map (mkVar var_getField `mkAppType`) $ reverse sels
 
 -- Turn a{b=c, ...} into setField calls
-onExp (L o upd@RecordUpd{rupd_expr,rupd_flds=L _ (HsRecField (fmap rdrNameAmbiguousFieldOcc -> lbl) arg pun):flds})
-    | let sel = mkSelector lbl
-    , let arg2 = if pun then noL $ HsVar noE lbl else arg
-    , let expr = mkParen $ mkVar var_setField `mkAppType` sel `mkApp` rupd_expr `mkApp` arg2  -- 'rupd_expr' never needs bracketing.
-    = onExp $ if null flds then expr else L o upd{rupd_expr=expr,rupd_flds=flds}
+onExp (L o upd@RecordUpd{rupd_expr,rupd_flds=fld:flds})
+    | adjacentBy 1 rupd_expr fld
+    = onExp $ f rupd_expr $ fld:flds
+    where
+        f expr [] = expr
+        f expr (L _ (HsRecField (fmap rdrNameAmbiguousFieldOcc -> lbl) arg pun) : flds)
+            | let sel = mkSelector lbl
+            , let arg2 = if pun then noL $ HsVar noE lbl else arg
+            , let expr2 = mkParen $ mkVar var_setField `mkAppType` sel `mkApp` expr `mkApp` arg2  -- 'expr' never needs bracketing.
+            = f expr2 flds
 
 onExp x = descend onExp x
 
@@ -196,7 +201,8 @@
 
 -- | Lens on: [r]{f1=x1}{f2=x2}
 getRec :: LHsExpr GhcPs -> (LHsExpr GhcPs -> LHsExpr GhcPs, LHsExpr GhcPs)
-getRec (L l r@RecordUpd{}) = first (\c x -> L l r{rupd_expr=c x}) $ getRec $ rupd_expr r
+-- important to copy the location back over, since we check the whitespace hasn't changed
+getRec (L l r@RecordUpd{}) = first (\c x -> L l r{rupd_expr=setL (getLoc $ rupd_expr r) $ c x}) $ getRec $ rupd_expr r
 getRec x = (id, x)
 
 -- | Is it equal to: .
@@ -215,4 +221,12 @@
 
 -- | Are the end of a and the start of b next to each other, no white space
 adjacent :: Located a -> Located b -> Bool
-adjacent (L a _) (L b _) = isGoodSrcSpan a && srcSpanEnd a == srcSpanStart b
+adjacent = adjacentBy 0
+
+-- | Are the end of a and the start of b next to each other, no white space
+adjacentBy :: Int -> Located a -> Located b -> Bool
+adjacentBy i (L (srcSpanEnd -> RealSrcLoc a) _) (L (srcSpanStart -> RealSrcLoc b) _) =
+    srcLocFile a == srcLocFile b &&
+    srcLocLine a == srcLocLine b &&
+    srcLocCol a + i == srcLocCol b
+adjacentBy _ _ _ = False
diff --git a/preprocessor/Edit.hs b/preprocessor/Edit.hs
--- a/preprocessor/Edit.hs
+++ b/preprocessor/Edit.hs
@@ -109,6 +109,7 @@
 editLoop (e:Paren (L "{") inner end:xs)
     | not $ isCtor e
     , not $ isPL "::" e
+    , getWhite e == ""
     , Just updates <- mapM f $ split (isPL ",") inner
     , let end2 = [Item end{lexeme=""} | whitespace end /= ""]
     = editLoop $ renderUpdate (Update e updates) : end2 ++ xs
diff --git a/record-dot-preprocessor.cabal b/record-dot-preprocessor.cabal
--- a/record-dot-preprocessor.cabal
+++ b/record-dot-preprocessor.cabal
@@ -1,7 +1,7 @@
 cabal-version:      >= 1.18
 build-type:         Simple
 name:               record-dot-preprocessor
-version:            0.2.1
+version:            0.2.2
 license:            BSD3
 x-license:          BSD-3-Clause OR Apache-2.0
 license-file:       LICENSE
