From d53908623bc1ca4e6390d8337533689344b74826 Mon Sep 17 00:00:00 2001
From: Hassan Al-Awwadi <hassan.awwadi@gmail.com>
Date: Thu, 10 Oct 2024 12:55:57 +0200
Subject: [PATCH] Put RdrName in the foExt field of FieldOcc

The main purpose of this commit is to rip RdrName out of FieldOcc, in
accordance with #21592, and as a side note it has simplified the method
we use to deal with ambiguity somewhat.

To do the first, we make FieldOccs store (LIdP p) instead of always
storing Located RdrName, and moved the readername to the extension
points where necessary.

For the second, well, we just turn an ambiguous RdrName into a unbound
Name through mkUnboundName. Later during disambiguateRecordBinds of the
type checking phase, we will try and do type-directed disambiguation based
on the rdrName field (for now), so this hack works out fine.

See Note [Ambiguous FieldOcc in record updates] for more details.

There are two additional minor changes in this commit:
*  The HsRecSel constructor of HsExpr has been moved to the extension
constuctors, since its really GHC specific.
*  HsProjection no longer has a Located DotFieldOcc as a field, but just a
regular DotFieldOcc, since DotFieldOcc already wraps a located
FieldLabelString

co-authored by: @Jade       <Jade512@proton.me>
                @alt-romes  <rodrigo.m.mesquita@gmail.com>

(cherry picked from commit 1587cccfe7c3c1db3ccc48437b47ccb6ae215701)
---
 compiler/GHC/Hs/Binds.hs                      |   3 +-
 compiler/GHC/Hs/Expr.hs                       |  40 ++++--
 compiler/GHC/Hs/Extension.hs                  |   2 +-
 compiler/GHC/Hs/Instances.hs                  |   6 -
 compiler/GHC/Hs/Pat.hs                        |  11 --
 compiler/GHC/Hs/Syn/Type.hs                   |   2 +-
 compiler/GHC/Hs/Type.hs                       | 114 +++++++++---------
 compiler/GHC/Hs/Utils.hs                      |   8 +-
 compiler/GHC/HsToCore/Docs.hs                 |   2 +-
 compiler/GHC/HsToCore/Expr.hs                 |  59 +++++----
 compiler/GHC/HsToCore/Quote.hs                |  31 +++--
 compiler/GHC/HsToCore/Ticks.hs                |   3 +-
 compiler/GHC/Iface/Ext/Ast.hs                 |  82 ++++++-------
 compiler/GHC/Parser/PostProcess.hs            |   6 +-
 compiler/GHC/Rename/Bind.hs                   |   2 +-
 compiler/GHC/Rename/Env.hs                    |   8 +-
 compiler/GHC/Rename/Expr.hs                   |  27 ++---
 compiler/GHC/Rename/Fixity.hs                 |   2 +-
 compiler/GHC/Rename/HsType.hs                 |  11 +-
 compiler/GHC/Rename/Pat.hs                    |  33 +++--
 compiler/GHC/Tc/Gen/Expr.hs                   |  19 ++-
 compiler/GHC/Tc/Gen/Head.hs                   |  15 ++-
 compiler/GHC/Tc/Gen/Pat.hs                    |  10 +-
 compiler/GHC/Tc/TyCl/Utils.hs                 |   3 +-
 compiler/GHC/Tc/Types/Origin.hs               |   2 +-
 compiler/GHC/Tc/Zonk/Type.hs                  |  11 +-
 compiler/GHC/ThToHs.hs                        |   4 +-
 compiler/Language/Haskell/Syntax/Expr.hs      |   6 +-
 compiler/Language/Haskell/Syntax/Extension.hs |   7 --
 compiler/Language/Haskell/Syntax/Pat.hs       |  14 +--
 compiler/Language/Haskell/Syntax/Type.hs      |  31 ++---
 .../tests/parser/should_compile/T14189.stderr |   6 +-
 utils/check-exact/ExactPrint.hs               |  24 ----
 .../src/Haddock/Backends/Hoogle.hs            |   2 +-
 .../haddock-api/src/Haddock/Backends/LaTeX.hs |   4 +-
 .../src/Haddock/Backends/Xhtml/Decl.hs        |   6 +-
 .../haddock-api/src/Haddock/Convert.hs        |   2 +-
 .../haddock-api/src/Haddock/GhcUtils.hs       |   4 +-
 .../src/Haddock/Interface/Create.hs           |   4 +-
 .../src/Haddock/Interface/Rename.hs           |   4 +-
 .../haddock/haddock-api/src/Haddock/Types.hs  |   4 +-
 41 files changed, 293 insertions(+), 341 deletions(-)

diff --git a/compiler/GHC/Hs/Binds.hs b/compiler/GHC/Hs/Binds.hs
index 72b3cb81110..6f00f0ef852 100644
--- a/compiler/GHC/Hs/Binds.hs
+++ b/compiler/GHC/Hs/Binds.hs
@@ -48,7 +48,6 @@ import GHC.Types.SourceText
 import GHC.Types.SrcLoc as SrcLoc
 import GHC.Types.Var
 import GHC.Data.BooleanFormula (LBooleanFormula)
-import GHC.Types.Name.Reader
 import GHC.Types.Name
 
 import GHC.Utils.Outputable
@@ -664,7 +663,7 @@ pprTicks pp_no_debug pp_when_debug
          then pp_when_debug
          else pp_no_debug
 
-instance Outputable (XRec a RdrName) => Outputable (RecordPatSynField a) where
+instance Outputable (XRec pass (IdP pass)) => Outputable (RecordPatSynField pass) where
     ppr (RecordPatSynField { recordPatSynField = v }) = ppr v
 
 
diff --git a/compiler/GHC/Hs/Expr.hs b/compiler/GHC/Hs/Expr.hs
index b2cfd2706af..08abb0b9bd2 100644
--- a/compiler/GHC/Hs/Expr.hs
+++ b/compiler/GHC/Hs/Expr.hs
@@ -554,6 +554,10 @@ data XXExprGhcRn
                                                    -- Does not presist post renaming phase
                                                    -- See Part 3. of Note [Expanding HsDo with XXExprGhcRn]
                                                    -- in `GHC.Tc.Gen.Do`
+  | HsRecSelRn  (FieldOcc GhcRn)   -- ^ Variable pointing to record selector
+                           -- See Note [Non-overloaded record field selectors] and
+                           -- Note [Record selectors in the AST]
+
 
 
 -- | Wrap a located expression with a `PopErrCtxt`
@@ -635,6 +639,11 @@ data XXExprGhcTc
      Int                                -- module-local tick number for False
      (LHsExpr GhcTc)                    -- sub-expression
 
+  | HsRecSelTc  (FieldOcc GhcTc) -- ^ Variable pointing to record selector
+                             -- See Note [Non-overloaded record field selectors] and
+                             -- Note [Record selectors in the AST]
+
+
 -- | Build a 'XXExprGhcRn' out of an extension constructor,
 --   and the two components of the expansion: original and
 --   expanded typechecked expressions.
@@ -695,7 +704,6 @@ ppr_expr :: forall p. (OutputableBndrId p)
          => HsExpr (GhcPass p) -> SDoc
 ppr_expr (HsVar _ (L _ v))   = pprPrefixOcc v
 ppr_expr (HsUnboundVar _ uv) = pprPrefixOcc uv
-ppr_expr (HsRecSel _ f)      = pprPrefixOcc f
 ppr_expr (HsIPVar _ v)       = ppr v
 ppr_expr (HsOverLabel s l) = case ghcPass @p of
                GhcPs -> helper s
@@ -914,11 +922,13 @@ instance Outputable HsThingRn where
         OrigExpr x -> ppr_builder "<OrigExpr>:" x
         OrigStmt x -> ppr_builder "<OrigStmt>:" x
         OrigPat x  -> ppr_builder "<OrigPat>:" x
+
     where ppr_builder prefix x = ifPprDebug (braces (text prefix <+> parens (ppr x))) (ppr x)
 
 instance Outputable XXExprGhcRn where
   ppr (ExpandedThingRn o e) = ifPprDebug (braces $ vcat [ppr o, ppr e]) (ppr o)
   ppr (PopErrCtxt e)        = ifPprDebug (braces (text "<PopErrCtxt>" <+> ppr e)) (ppr e)
+  ppr (HsRecSelRn f)        = pprPrefixOcc f
 
 instance Outputable XXExprGhcTc where
   ppr (WrapExpr co_fn e)
@@ -947,10 +957,11 @@ instance Outputable XXExprGhcTc where
             ppr tickIdFalse,
             text ">(",
             ppr exp, text ")"]
+  ppr (HsRecSelTc f)      = pprPrefixOcc f
+
 
 ppr_infix_expr :: forall p. (OutputableBndrId p) => HsExpr (GhcPass p) -> Maybe SDoc
 ppr_infix_expr (HsVar _ (L _ v))    = Just (pprInfixOcc v)
-ppr_infix_expr (HsRecSel _ f)       = Just (pprInfixOcc f)
 ppr_infix_expr (HsUnboundVar _ occ) = Just (pprInfixOcc occ)
 ppr_infix_expr (XExpr x)            = case ghcPass @p of
                                         GhcRn -> ppr_infix_expr_rn x
@@ -959,7 +970,8 @@ ppr_infix_expr _ = Nothing
 
 ppr_infix_expr_rn :: XXExprGhcRn -> Maybe SDoc
 ppr_infix_expr_rn (ExpandedThingRn thing _) = ppr_infix_hs_expansion thing
-ppr_infix_expr_rn (PopErrCtxt (L _ a)) = ppr_infix_expr a
+ppr_infix_expr_rn (PopErrCtxt (L _ a))      = ppr_infix_expr a
+ppr_infix_expr_rn (HsRecSelRn f)            = Just (pprInfixOcc f)
 
 ppr_infix_expr_tc :: XXExprGhcTc -> Maybe SDoc
 ppr_infix_expr_tc (WrapExpr _ e)    = ppr_infix_expr e
@@ -967,6 +979,8 @@ ppr_infix_expr_tc (ExpandedThingTc thing _)  = ppr_infix_hs_expansion thing
 ppr_infix_expr_tc (ConLikeTc {})             = Nothing
 ppr_infix_expr_tc (HsTick {})                = Nothing
 ppr_infix_expr_tc (HsBinTick {})             = Nothing
+ppr_infix_expr_tc (HsRecSelTc f)            = Just (pprInfixOcc f)
+
 
 ppr_infix_hs_expansion :: HsThingRn -> Maybe SDoc
 ppr_infix_hs_expansion (OrigExpr e) = ppr_infix_expr e
@@ -1053,7 +1067,6 @@ hsExprNeedsParens prec = go
     go (HsProc{})                     = prec > topPrec
     go (HsStatic{})                   = prec >= appPrec
     go (RecordCon{})                  = False
-    go (HsRecSel{})                   = False
     go (HsProjection{})               = True
     go (HsGetField{})                 = False
     go (HsEmbTy{})                    = prec > topPrec
@@ -1070,10 +1083,12 @@ hsExprNeedsParens prec = go
     go_x_tc (ConLikeTc {})                   = False
     go_x_tc (HsTick _ (L _ e))               = hsExprNeedsParens prec e
     go_x_tc (HsBinTick _ _ (L _ e))          = hsExprNeedsParens prec e
+    go_x_tc (HsRecSelTc{})                   = False
 
     go_x_rn :: XXExprGhcRn -> Bool
     go_x_rn (ExpandedThingRn thing _)    = hsExpandedNeedsParens thing
     go_x_rn (PopErrCtxt (L _ a))         = hsExprNeedsParens prec a
+    go_x_rn (HsRecSelRn{})               = False
 
     hsExpandedNeedsParens :: HsThingRn -> Bool
     hsExpandedNeedsParens (OrigExpr e) = hsExprNeedsParens prec e
@@ -1111,21 +1126,22 @@ isAtomicHsExpr (HsOverLit {})    = True
 isAtomicHsExpr (HsIPVar {})      = True
 isAtomicHsExpr (HsOverLabel {})  = True
 isAtomicHsExpr (HsUnboundVar {}) = True
-isAtomicHsExpr (HsRecSel{})      = True
 isAtomicHsExpr (XExpr x)
   | GhcTc <- ghcPass @p          = go_x_tc x
   | GhcRn <- ghcPass @p          = go_x_rn x
   where
     go_x_tc :: XXExprGhcTc -> Bool
-    go_x_tc (WrapExpr _ e)                   = isAtomicHsExpr e
-    go_x_tc (ExpandedThingTc thing _)        = isAtomicExpandedThingRn thing
-    go_x_tc (ConLikeTc {})                   = True
-    go_x_tc (HsTick {}) = False
-    go_x_tc (HsBinTick {}) = False
+    go_x_tc (WrapExpr _ e)            = isAtomicHsExpr e
+    go_x_tc (ExpandedThingTc thing _) = isAtomicExpandedThingRn thing
+    go_x_tc (ConLikeTc {})            = True
+    go_x_tc (HsTick {})               = False
+    go_x_tc (HsBinTick {})            = False
+    go_x_tc (HsRecSelTc{})            = True
 
     go_x_rn :: XXExprGhcRn -> Bool
-    go_x_rn (ExpandedThingRn thing _)    = isAtomicExpandedThingRn thing
-    go_x_rn (PopErrCtxt (L _ a))         = isAtomicHsExpr a
+    go_x_rn (ExpandedThingRn thing _) = isAtomicExpandedThingRn thing
+    go_x_rn (PopErrCtxt (L _ a))      = isAtomicHsExpr a
+    go_x_rn (HsRecSelRn{})            = True
 
     isAtomicExpandedThingRn :: HsThingRn -> Bool
     isAtomicExpandedThingRn (OrigExpr e) = isAtomicHsExpr e
diff --git a/compiler/GHC/Hs/Extension.hs b/compiler/GHC/Hs/Extension.hs
index bf2e67731d9..a921f4cf9a2 100644
--- a/compiler/GHC/Hs/Extension.hs
+++ b/compiler/GHC/Hs/Extension.hs
@@ -244,4 +244,4 @@ instance Outputable NoExtField where
   ppr _ = text "NoExtField"
 
 instance Outputable DataConCantHappen where
-  ppr = dataConCantHappen
\ No newline at end of file
+  ppr = dataConCantHappen
diff --git a/compiler/GHC/Hs/Instances.hs b/compiler/GHC/Hs/Instances.hs
index 5326ae27460..de9230eb86a 100644
--- a/compiler/GHC/Hs/Instances.hs
+++ b/compiler/GHC/Hs/Instances.hs
@@ -558,12 +558,6 @@ deriving instance Data (FieldOcc GhcPs)
 deriving instance Data (FieldOcc GhcRn)
 deriving instance Data (FieldOcc GhcTc)
 
--- deriving instance DataId p       => Data (AmbiguousFieldOcc p)
-deriving instance Data (AmbiguousFieldOcc GhcPs)
-deriving instance Data (AmbiguousFieldOcc GhcRn)
-deriving instance Data (AmbiguousFieldOcc GhcTc)
-
-
 -- deriving instance (DataId name) => Data (ImportDecl name)
 deriving instance Data (ImportDecl GhcPs)
 deriving instance Data (ImportDecl GhcRn)
diff --git a/compiler/GHC/Hs/Pat.hs b/compiler/GHC/Hs/Pat.hs
index 587793828eb..8b357f9b7c3 100644
--- a/compiler/GHC/Hs/Pat.hs
+++ b/compiler/GHC/Hs/Pat.hs
@@ -38,7 +38,6 @@ module GHC.Hs.Pat (
         HsRecUpdField, LHsRecUpdField,
         RecFieldsDotDot(..),
         hsRecFields, hsRecFieldSel, hsRecFieldId, hsRecFieldsArgs,
-        hsRecUpdFieldId, hsRecUpdFieldOcc, hsRecUpdFieldRdr,
 
         mkPrefixConPat, mkCharLitPat, mkNilPat,
 
@@ -341,16 +340,6 @@ data ConPatTc
 hsRecFieldId :: HsRecField GhcTc arg -> Id
 hsRecFieldId = hsRecFieldSel
 
-hsRecUpdFieldRdr :: HsRecUpdField (GhcPass p) q -> Located RdrName
-hsRecUpdFieldRdr = fmap ambiguousFieldOccRdrName . reLoc . hfbLHS
-
-hsRecUpdFieldId :: HsFieldBind (LAmbiguousFieldOcc GhcTc) arg -> Located Id
-hsRecUpdFieldId = fmap foExt . reLoc . hsRecUpdFieldOcc
-
-hsRecUpdFieldOcc :: HsFieldBind (LAmbiguousFieldOcc GhcTc) arg -> LFieldOcc GhcTc
-hsRecUpdFieldOcc = fmap unambiguousFieldOcc . hfbLHS
-
-
 {-
 ************************************************************************
 *                                                                      *
diff --git a/compiler/GHC/Hs/Syn/Type.hs b/compiler/GHC/Hs/Syn/Type.hs
index 98c15767a0a..3c550deacd5 100644
--- a/compiler/GHC/Hs/Syn/Type.hs
+++ b/compiler/GHC/Hs/Syn/Type.hs
@@ -103,7 +103,6 @@ lhsExprType (L _ e) = hsExprType e
 hsExprType :: HsExpr GhcTc -> Type
 hsExprType (HsVar _ (L _ id)) = idType id
 hsExprType (HsUnboundVar (HER _ ty _) _) = ty
-hsExprType (HsRecSel _ (FieldOcc id _)) = idType id
 hsExprType (HsOverLabel v _) = dataConCantHappen v
 hsExprType (HsIPVar v _) = dataConCantHappen v
 hsExprType (HsOverLit _ lit) = overLitType lit
@@ -154,6 +153,7 @@ hsExprType (XExpr (ExpandedThingTc _ e))  = hsExprType e
 hsExprType (XExpr (ConLikeTc con _ _)) = conLikeType con
 hsExprType (XExpr (HsTick _ e)) = lhsExprType e
 hsExprType (XExpr (HsBinTick _ _ e)) = lhsExprType e
+hsExprType (XExpr (HsRecSelTc (FieldOcc _ id))) = idType (unLoc id)
 
 arithSeqInfoType :: ArithSeqInfo GhcTc -> Type
 arithSeqInfoType asi = mkListTy $ case asi of
diff --git a/compiler/GHC/Hs/Type.hs b/compiler/GHC/Hs/Type.hs
index 7a467d675a4..4ff5ed43c54 100644
--- a/compiler/GHC/Hs/Type.hs
+++ b/compiler/GHC/Hs/Type.hs
@@ -59,12 +59,8 @@ module GHC.Hs.Type (
         ConDeclField(..), LConDeclField, pprConDeclFields,
 
         HsConDetails(..), noTypeArgs,
-
         FieldOcc(..), LFieldOcc, mkFieldOcc,
-        AmbiguousFieldOcc(..), LAmbiguousFieldOcc, mkAmbiguousFieldOcc,
-        ambiguousFieldOccRdrName, ambiguousFieldOccLRdrName,
-        selectorAmbiguousFieldOcc,
-        unambiguousFieldOcc, ambiguousFieldOcc,
+        fieldOccRdrName, fieldOccLRdrName,
 
         OpName(..),
 
@@ -115,7 +111,6 @@ import GHC.Hs.Extension
 import GHC.Parser.Annotation
 
 import GHC.Types.Fixity ( LexicalFixity(..) )
-import GHC.Types.Id ( Id )
 import GHC.Types.SourceText
 import GHC.Types.Name
 import GHC.Types.Name.Reader ( RdrName )
@@ -1097,59 +1092,62 @@ also forbids them in types involved with `deriving`:
                 FieldOcc
 *                                                                      *
 ************************************************************************
+
+Note [Ambiguous FieldOcc in record updates]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+When renaming a "record field update" (`some_record{ field = expr }`), the field
+occurrence may be ambiguous if there are multiple record types with that same
+field label in scope. Instead of failing, we may attempt to do type-directed
+disambiguation: if we typecheck the record field update, we can disambiguate
+the `field` based on the record and field type.
+
+In practice, this means an identifier of a field occurrence
+(`FieldOcc`) may have to go straight from `RdrName` to `Id`, since field
+ambiguity makes it impossible to construct a `Name` for the field.
+
+Since type-directed disambiguation is a GHC property rather than a property of
+the GHC-Haskell AST, we still parameterise a `FieldOcc` occurrence by `IdP p`,
+but in the case of the ambiguity we do the unthinkable and insert a mkUnboundName
+in the name. Very bad, yes, but since type-directed disambiguation is on the way
+out (see proposal https://github.com/ghc-proposals/ghc-proposals/pull/366),
+we consider this acceptable for now.
+
+see also Wrinkle [Disambiguating fields] and note [Type-directed record disambiguation]
+
+NB: FieldOcc preserves the RdrName throughout its lifecycle for
+exact printing purposes.
 -}
 
-type instance XCFieldOcc GhcPs = NoExtField
-type instance XCFieldOcc GhcRn = Name
-type instance XCFieldOcc GhcTc = Id
+type instance XCFieldOcc GhcPs = NoExtField -- RdrName is stored in the proper IdP field
+type instance XCFieldOcc GhcRn = RdrName
+type instance XCFieldOcc GhcTc = RdrName
 
-type instance XXFieldOcc (GhcPass _) = DataConCantHappen
+type instance XXFieldOcc GhcPs = DataConCantHappen
+type instance XXFieldOcc GhcRn = DataConCantHappen
+type instance XXFieldOcc GhcTc = DataConCantHappen
+
+--------------------------------------------------------------------------------
 
 mkFieldOcc :: LocatedN RdrName -> FieldOcc GhcPs
 mkFieldOcc rdr = FieldOcc noExtField rdr
 
+fieldOccRdrName :: forall p. IsPass p => FieldOcc (GhcPass p) -> RdrName
+fieldOccRdrName fo = case ghcPass @p of
+  GhcPs -> unLoc $ foLabel fo
+  GhcRn -> foExt fo
+  GhcTc -> foExt fo
 
-type instance XUnambiguous GhcPs = NoExtField
-type instance XUnambiguous GhcRn = Name
-type instance XUnambiguous GhcTc = Id
-
-type instance XAmbiguous GhcPs = NoExtField
-type instance XAmbiguous GhcRn = NoExtField
-type instance XAmbiguous GhcTc = Id
-
-type instance XXAmbiguousFieldOcc (GhcPass _) = DataConCantHappen
-
-instance Outputable (AmbiguousFieldOcc (GhcPass p)) where
-  ppr = ppr . ambiguousFieldOccRdrName
-
-instance OutputableBndr (AmbiguousFieldOcc (GhcPass p)) where
-  pprInfixOcc  = pprInfixOcc . ambiguousFieldOccRdrName
-  pprPrefixOcc = pprPrefixOcc . ambiguousFieldOccRdrName
-
-instance OutputableBndr (Located (AmbiguousFieldOcc (GhcPass p))) where
-  pprInfixOcc  = pprInfixOcc . unLoc
-  pprPrefixOcc = pprPrefixOcc . unLoc
-
-mkAmbiguousFieldOcc :: LocatedN RdrName -> AmbiguousFieldOcc GhcPs
-mkAmbiguousFieldOcc rdr = Unambiguous noExtField rdr
-
-ambiguousFieldOccRdrName :: AmbiguousFieldOcc (GhcPass p) -> RdrName
-ambiguousFieldOccRdrName = unLoc . ambiguousFieldOccLRdrName
+fieldOccLRdrName :: forall p. IsPass p => FieldOcc (GhcPass p) -> LocatedN RdrName
+fieldOccLRdrName fo = case ghcPass @p of
+  GhcPs -> foLabel fo
+  GhcRn -> case fo of
+    FieldOcc rdr sel ->
+      let (L l _) = sel
+       in L l rdr
+  GhcTc ->
+    let (L l _) = foLabel fo
+     in L l (foExt fo)
 
-ambiguousFieldOccLRdrName :: AmbiguousFieldOcc (GhcPass p) -> LocatedN RdrName
-ambiguousFieldOccLRdrName (Unambiguous _ rdr) = rdr
-ambiguousFieldOccLRdrName (Ambiguous   _ rdr) = rdr
-
-selectorAmbiguousFieldOcc :: AmbiguousFieldOcc GhcTc -> Id
-selectorAmbiguousFieldOcc (Unambiguous sel _) = sel
-selectorAmbiguousFieldOcc (Ambiguous   sel _) = sel
-
-unambiguousFieldOcc :: AmbiguousFieldOcc GhcTc -> FieldOcc GhcTc
-unambiguousFieldOcc (Unambiguous rdr sel) = FieldOcc rdr sel
-unambiguousFieldOcc (Ambiguous   rdr sel) = FieldOcc rdr sel
-
-ambiguousFieldOcc :: FieldOcc GhcTc -> AmbiguousFieldOcc GhcTc
-ambiguousFieldOcc (FieldOcc sel rdr) = Unambiguous sel rdr
 
 {-
 ************************************************************************
@@ -1279,18 +1277,19 @@ instance (Outputable tyarg, Outputable arg, Outputable rec)
   ppr (RecCon rec)            = text "RecCon:" <+> ppr rec
   ppr (InfixCon l r)          = text "InfixCon:" <+> ppr [l, r]
 
-instance Outputable (XRec pass RdrName) => Outputable (FieldOcc pass) where
+instance Outputable (XRec pass (IdP pass)) => Outputable (FieldOcc pass) where
   ppr = ppr . foLabel
 
-instance (UnXRec pass, OutputableBndr (XRec pass RdrName)) => OutputableBndr (FieldOcc pass) where
-  pprInfixOcc  = pprInfixOcc . unXRec @pass . foLabel
-  pprPrefixOcc = pprPrefixOcc . unXRec @pass . foLabel
+instance (OutputableBndrId pass) => OutputableBndr (FieldOcc (GhcPass pass)) where
+  pprInfixOcc  = pprInfixOcc . unXRec @(GhcPass pass) . foLabel
+  pprPrefixOcc = pprPrefixOcc . unXRec @(GhcPass pass) . foLabel
 
-instance (UnXRec pass, OutputableBndr (XRec pass RdrName)) => OutputableBndr (GenLocated SrcSpan (FieldOcc pass)) where
+instance (OutputableBndrId pass) => OutputableBndr (GenLocated SrcSpan (FieldOcc (GhcPass pass))) where
   pprInfixOcc  = pprInfixOcc . unLoc
   pprPrefixOcc = pprPrefixOcc . unLoc
 
 
+
 ppr_tylit :: (HsTyLit (GhcPass p)) -> SDoc
 ppr_tylit (HsNumTy source i) = pprWithSourceText source (integer i)
 ppr_tylit (HsStrTy source s) = pprWithSourceText source (text (show s))
@@ -1351,7 +1350,7 @@ pprLHsContextAlways (L _ ctxt)
       [L _ ty] -> ppr_mono_ty ty           <+> darrow
       _        -> parens (interpp'SP ctxt) <+> darrow
 
-pprConDeclFields :: OutputableBndrId p
+pprConDeclFields :: forall p. OutputableBndrId p
                  => [LConDeclField (GhcPass p)] -> SDoc
 pprConDeclFields fields = braces (sep (punctuate comma (map ppr_fld fields)))
   where
@@ -1359,7 +1358,7 @@ pprConDeclFields fields = braces (sep (punctuate comma (map ppr_fld fields)))
                                  cd_fld_doc = doc }))
         = pprMaybeWithDoc doc (ppr_names ns <+> dcolon <+> ppr ty)
 
-    ppr_names :: [LFieldOcc (GhcPass p)] -> SDoc
+    ppr_names :: forall p. OutputableBndrId p => [LFieldOcc (GhcPass p)] -> SDoc
     ppr_names [n] = pprPrefixOcc n
     ppr_names ns = sep (punctuate comma (map pprPrefixOcc ns))
 
@@ -1587,4 +1586,3 @@ type instance Anno HsIPName = EpAnnCO
 type instance Anno (ConDeclField (GhcPass p)) = SrcSpanAnnA
 
 type instance Anno (FieldOcc (GhcPass p)) = SrcSpanAnnA
-type instance Anno (AmbiguousFieldOcc (GhcPass p)) = SrcSpanAnnA
diff --git a/compiler/GHC/Hs/Utils.hs b/compiler/GHC/Hs/Utils.hs
index 40bc935195c..4c5477ef568 100644
--- a/compiler/GHC/Hs/Utils.hs
+++ b/compiler/GHC/Hs/Utils.hs
@@ -1442,7 +1442,7 @@ hsTyClForeignBinders tycl_decls foreign_decls
          (foldMap (foldMap hsLInstDeclBinders . group_instds) tycl_decls))
   where
     getSelectorNames :: ([LocatedA Name], [LFieldOcc GhcRn]) -> [Name]
-    getSelectorNames (ns, fs) = map unLoc ns ++ map (foExt . unLoc) fs
+    getSelectorNames (ns, fs) = map unLoc ns ++ map (unLoc . foLabel . unLoc) fs
 
 -------------------
 
@@ -1684,7 +1684,7 @@ emptyFieldIndices =
                , fieldIndices = Map.empty
                , newInt       = 0 }
 
-insertField :: LFieldOcc (GhcPass p) -> FieldIndices p -> (Located Int, FieldIndices p)
+insertField :: IsPass p => LFieldOcc (GhcPass p) -> FieldIndices p -> (Located Int, FieldIndices p)
 insertField new_fld fi@(FieldIndices flds idxs new_idx)
   | Just i <- Map.lookup rdr idxs
   = (L loc i, fi)
@@ -1695,7 +1695,7 @@ insertField new_fld fi@(FieldIndices flds idxs new_idx)
                    (new_idx + 1))
   where
     loc = getLocA new_fld
-    rdr = unLoc . foLabel . unLoc $ new_fld
+    rdr = fieldOccRdrName . unLoc $ new_fld
 
 {-
 
@@ -1871,5 +1871,5 @@ rec_field_expl_impl rec_flds (RecFieldsDotDot { .. })
   where (explicit_binds, implicit_binds) = splitAt unRecFieldsDotDot rec_flds
         implicit_field_binders (L _ (HsFieldBind { hfbLHS = L _ fld, hfbRHS = rhs }))
           = ImplicitFieldBinders
-              { implFlBndr_field   = foExt fld
+              { implFlBndr_field   = unLoc $ foLabel fld
               , implFlBndr_binders = collectPatBinders CollNoDictBinders rhs }
diff --git a/compiler/GHC/HsToCore/Docs.hs b/compiler/GHC/HsToCore/Docs.hs
index da73bfd1ebc..acf0053cc6a 100644
--- a/compiler/GHC/HsToCore/Docs.hs
+++ b/compiler/GHC/HsToCore/Docs.hs
@@ -394,7 +394,7 @@ subordinates env instMap decl = case decl of
                     , maybeToList $ fmap unLoc $ con_doc c
                     , conArgDocs c)
                   | c <- toList cons, cname <- getConNames c ]
-        fields  = [ (foExt n, maybeToList $ fmap unLoc doc, IM.empty)
+        fields  = [ (unLoc $ foLabel n, maybeToList $ fmap unLoc doc, IM.empty)
                   | Just flds <- toList $ fmap getRecConArgs_maybe cons
                   , (L _ (ConDeclField _ ns _ doc)) <- (unLoc flds)
                   , (L _ n) <- ns ]
diff --git a/compiler/GHC/HsToCore/Expr.hs b/compiler/GHC/HsToCore/Expr.hs
index 5bf8bb10f0d..eff00f86786 100644
--- a/compiler/GHC/HsToCore/Expr.hs
+++ b/compiler/GHC/HsToCore/Expr.hs
@@ -261,36 +261,6 @@ dsLExpr (L loc e) = putSrcSpanDsA loc $ dsExpr e
 dsExpr :: HsExpr GhcTc -> DsM CoreExpr
 dsExpr (HsVar    _ (L _ id))           = dsHsVar id
 
-{- Record selectors are warned about if they are not
-present in all of the parent data type's constructor,
-or always in case of pattern synonym record selectors
-(regulated by a flag). However, this only produces
-a warning if it's not a part of a record selector
-application. For example:
-
-        data T = T1 | T2 {s :: Bool}
-        f x = s x -- the warning from this case will be supressed
-
-See the `HsApp` case for where it is filtered out
--}
-dsExpr (HsRecSel _ (FieldOcc id _))
-  = do { let name = getName id
-             RecSelId {sel_cons = (_, cons_wo_field)}
-                  = idDetails id
-       ; cons_trimmed <- trim_cons cons_wo_field
-       ; unless (null cons_wo_field) $ diagnosticDs
-             $ DsIncompleteRecordSelector name cons_trimmed (cons_trimmed /= cons_wo_field)
-                 -- This only produces a warning if it's not a part of a
-                 -- record selector application (e.g. `s a` where `s` is a selector)
-                 -- See the `HsApp` case for where it is filtered out
-       ; dsHsVar id }
-  where
-    trim_cons :: [ConLike] -> DsM [ConLike]
-    trim_cons cons_wo_field = do
-      dflags <- getDynFlags
-      let maxConstructors = maxUncoveredPatterns dflags
-      return $ take maxConstructors cons_wo_field
-
 
 dsExpr (HsUnboundVar (HER ref _ _) _)  = dsEvTerm =<< readMutVar ref
         -- See Note [Holes] in GHC.Tc.Types.Constraint
@@ -336,6 +306,35 @@ dsExpr e@(XExpr ext_expr_tc)
         do { assert (exprType e2 `eqType` boolTy)
             mkBinaryTickBox ixT ixF e2
           }
+        {- Record selectors are warned about if they are not
+        present in all of the parent data type's constructor,
+        or always in case of pattern synonym record selectors
+        (regulated by a flag). However, this only produces
+        a warning if it's not a part of a record selector
+        application. For example:
+
+                data T = T1 | T2 {s :: Bool}
+                f x = s x -- the warning from this case will be supressed
+
+        See the `HsApp` case for where it is filtered out
+        -}
+      (HsRecSelTc (FieldOcc _ (L _ id))) ->
+        do { let  name = getName id
+                  RecSelId {sel_cons = (_, cons_wo_field)} = idDetails id
+            ; cons_trimmed <- trim_cons cons_wo_field
+            ; unless (null cons_wo_field) $ diagnosticDs
+                  $ DsIncompleteRecordSelector name cons_trimmed (cons_trimmed /= cons_wo_field)
+                      -- This only produces a warning if it's not a part of a
+                      -- record selector application (e.g. `s a` where `s` is a selector)
+                      -- See the `HsApp` case for where it is filtered out
+            ; dsHsVar id }
+          where
+            trim_cons :: [ConLike] -> DsM [ConLike]
+            trim_cons cons_wo_field = do
+              dflags <- getDynFlags
+              let maxConstructors = maxUncoveredPatterns dflags
+              return $ take maxConstructors cons_wo_field
+
 
 -- Strip ticks due to #21701, need to be invariant about warnings we produce whether
 -- this is enabled or not.
diff --git a/compiler/GHC/HsToCore/Quote.hs b/compiler/GHC/HsToCore/Quote.hs
index 4681c6b6be6..85c56b3a310 100644
--- a/compiler/GHC/HsToCore/Quote.hs
+++ b/compiler/GHC/HsToCore/Quote.hs
@@ -284,7 +284,7 @@ repTopDs group@(HsGroup { hs_valds   = valds
                         , hs_docs    = docs })
  = do { let { bndrs  = hsScopedTvBinders valds
                        ++ hsGroupBinders group
-                       ++ map foExt (hsPatSynSelectors valds)
+                       ++ map (unLoc . foLabel) (hsPatSynSelectors valds)
             ; instds = tyclds >>= group_instds } ;
         ss <- mkGenSyms bndrs ;
 
@@ -1544,7 +1544,6 @@ repE (HsVar _ (L _ x)) =
 repE (HsIPVar _ n) = rep_implicit_param_name n >>= repImplicitParamVar
 repE (HsOverLabel _ s) = repOverLabel s
 
-repE (HsRecSel _ (FieldOcc x _)) = repE (HsVar noExtField (noLocA x))
 
         -- Remember, we're desugaring renamer output here, so
         -- HsOverlit can definitely occur
@@ -1686,7 +1685,7 @@ repE (HsUnboundVar _ uv)   = do
 repE (HsGetField _ e (L _ (DotFieldOcc _ (L _ (FieldLabelString f))))) = do
   e1 <- repLE e
   repGetField e1 f
-repE (HsProjection _ xs) = repProjection (fmap (field_label . unLoc . dfoLabel . unLoc) xs)
+repE (HsProjection _ xs) = repProjection (fmap (field_label . unLoc . dfoLabel) xs)
 repE (HsEmbTy _ t) = do
   t1 <- repLTy (hswc_body t)
   rep2 typeEName [unC t1]
@@ -1719,6 +1718,8 @@ repE e@(XExpr (ExpandedThingRn o x))
   = notHandled (ThExpressionForm e)
 
 repE (XExpr (PopErrCtxt (L _ e))) = repE e
+repE (XExpr (HsRecSelRn (FieldOcc _ (L _ x)))) = repE (HsVar noExtField (noLocA x))
+
 repE e@(HsPragE _ (HsPragSCC {}) _) = notHandled (ThCostCentres e)
 repE e@(HsTypedBracket{})   = notHandled (ThExpressionForm e)
 repE e@(HsUntypedBracket{}) = notHandled (ThExpressionForm e)
@@ -1821,11 +1822,19 @@ repUpdFields :: [LHsRecUpdField GhcRn GhcRn] -> MetaM (Core [M TH.FieldExp])
 repUpdFields = repListM fieldExpTyConName rep_fld
   where
     rep_fld :: LHsRecUpdField GhcRn GhcRn -> MetaM (Core (M TH.FieldExp))
-    rep_fld (L l fld) = case unLoc (hfbLHS fld) of
-      Unambiguous sel_name _ -> do { fn <- lookupLOcc (L l sel_name)
-                                   ; e  <- repLE (hfbRHS fld)
-                                   ; repFieldExp fn e }
-      Ambiguous{}            -> notHandled (ThAmbiguousRecordUpdates fld)
+    rep_fld (L l fld) =
+      let (FieldOcc _ (L _ sel_name)) = unLoc (hfbLHS fld)
+      -- If we have an unbountName in the sel_name, that means we failed to
+      -- disambiguate during the Rename stage of Ghc. Now if we continued
+      -- onwards to type checking that might be fine, as explained in
+      -- Note [Ambiguous FieldOcc in record updates], but if instead we
+      -- are within the context of Template Haskell, we just fail immediately.
+      in if  isUnboundName sel_name
+       then  notHandled (ThAmbiguousRecordUpdates fld)
+       else  do  { fn <- lookupLOcc (L l sel_name)
+                 ; e  <- repLE (hfbRHS fld)
+                 ; repFieldExp fn e
+                 }
 
 
 
@@ -2028,7 +2037,7 @@ rep_bind (L loc (PatSynBind _ (PSB { psb_id   = syn
     mkGenArgSyms (InfixCon arg1 arg2) = mkGenSyms [unLoc arg1, unLoc arg2]
     mkGenArgSyms (RecCon fields)
       = do { let pats = map (unLoc . recordPatSynPatVar) fields
-                 sels = map (foExt . recordPatSynField) fields
+                 sels = map (unLoc . foLabel . recordPatSynField) fields
            ; ss <- mkGenSyms sels
            ; return $ replaceNames (zip sels pats) ss }
 
@@ -2060,7 +2069,7 @@ repPatSynArgs (InfixCon arg1 arg2)
        ; arg2' <- lookupLOcc arg2
        ; repInfixPatSynArgs arg1' arg2' }
 repPatSynArgs (RecCon fields)
-  = do { sels' <- repList nameTyConName (lookupOcc . foExt) sels
+  = do { sels' <- repList nameTyConName (lookupOcc . unLoc . foLabel) sels
        ; repRecordPatSynArgs sels' }
   where sels = map recordPatSynField fields
 
@@ -2883,7 +2892,7 @@ repRecConArgs ips = do
       rep_ip (L _ ip) = mapM (rep_one_ip (cd_fld_type ip)) (cd_fld_names ip)
 
       rep_one_ip :: LBangType GhcRn -> LFieldOcc GhcRn -> MetaM (Core (M TH.VarBangType))
-      rep_one_ip t n = do { MkC v  <- lookupOcc (foExt $ unLoc n)
+      rep_one_ip t n = do { MkC v  <- lookupOcc (unLoc . foLabel $ unLoc n)
                           ; MkC ty <- repBangTy  t
                           ; rep2 varBangTypeName [v,ty] }
 
diff --git a/compiler/GHC/HsToCore/Ticks.hs b/compiler/GHC/HsToCore/Ticks.hs
index 4c743ff9c16..594d308192a 100644
--- a/compiler/GHC/HsToCore/Ticks.hs
+++ b/compiler/GHC/HsToCore/Ticks.hs
@@ -476,7 +476,6 @@ addBinTickLHsExpr boxLabel e@(L pos e0)
 addTickHsExpr :: HsExpr GhcTc -> TM (HsExpr GhcTc)
 addTickHsExpr e@(HsVar _ (L _ id))  = do freeVar id; return e
 addTickHsExpr e@(HsUnboundVar {})   = return e
-addTickHsExpr e@(HsRecSel _ (FieldOcc id _))   = do freeVar id; return e
 
 addTickHsExpr e@(HsIPVar {})            = return e
 addTickHsExpr e@(HsOverLit {})          = return e
@@ -604,6 +603,8 @@ addTickHsExpr (XExpr (HsTick t e)) =
 addTickHsExpr (XExpr (HsBinTick t0 t1 e)) =
         liftM (XExpr . HsBinTick t0 t1) (addTickLHsExprNever e)
 
+addTickHsExpr e@(XExpr (HsRecSelTc (FieldOcc _ id)))   = do freeVar (unLoc id); return e
+
 addTickHsExpr (HsDo srcloc cxt (L l stmts))
   = do { (stmts', _) <- addTickLStmts' forQual stmts (return ())
        ; return (HsDo srcloc cxt (L l stmts')) }
diff --git a/compiler/GHC/Iface/Ext/Ast.hs b/compiler/GHC/Iface/Ext/Ast.hs
index 8b88fa7914f..f9ebdfa01b5 100644
--- a/compiler/GHC/Iface/Ext/Ast.hs
+++ b/compiler/GHC/Iface/Ext/Ast.hs
@@ -828,7 +828,6 @@ class ( HiePass (NoGhcTcPass p)
       , Data (Stmt  (GhcPass p) (LocatedA (HsCmd  (GhcPass p))))
       , Data (HsExpr (GhcPass p))
       , Data (HsCmd  (GhcPass p))
-      , Data (AmbiguousFieldOcc (GhcPass p))
       , Data (HsCmdTop (GhcPass p))
       , Data (GRHS (GhcPass p) (LocatedA (HsCmd (GhcPass p))))
       , Data (HsUntypedSplice (GhcPass p))
@@ -1205,9 +1204,6 @@ instance HiePass p => ToHie (LocatedA (HsExpr (GhcPass p))) where
              -- Patch up var location since typechecker removes it
         ]
       HsUnboundVar _ _ -> []  -- there is an unbound name here, but that causes trouble
-      HsRecSel _ fld ->
-        [ toHie $ RFC RecFieldOcc Nothing (L mspan fld)
-        ]
       HsOverLabel {} -> []
       HsIPVar _ _ -> []
       HsOverLit _ o ->
@@ -1285,7 +1281,9 @@ instance HiePass p => ToHie (LocatedA (HsExpr (GhcPass p))) where
       RecordUpd { rupd_expr = expr
                 , rupd_flds = RegularRecUpdFields { recUpdFields = upds } }->
         [ toHie expr
-        , toHie $ map (RC RecFieldAssign) upds
+        , case hiePass @p of
+          HieRn -> toHie $ map (RC RecFieldAssign) upds
+          HieTc -> toHie $ map (RC RecFieldAssign) upds
         ]
       RecordUpd { rupd_expr = expr
                 , rupd_flds = OverloadedRecUpdFields {} }->
@@ -1353,23 +1351,29 @@ instance HiePass p => ToHie (LocatedA (HsExpr (GhcPass p))) where
         ]
       HsGetField {} -> []
       HsProjection {} -> []
-      XExpr x
-        | HieTc <- hiePass @p
-        -> case x of
-             WrapExpr w a
-               -> [ toHie $ L mspan a
-                  , toHie (L mspan w) ]
-             ExpandedThingTc _ e
-               -> [ toHie (L mspan e) ]
-             ConLikeTc con _ _
-               -> [ toHie $ C Use $ L mspan $ conLikeName con ]
-             HsTick _ expr
-               -> [ toHie expr
-                  ]
-             HsBinTick _ _ expr
-               -> [ toHie expr
-                  ]
-        | otherwise -> []
+      XExpr x -> case hiePass @p of
+        HieTc -> case x of
+          WrapExpr w a
+            -> [ toHie $ L mspan a
+               , toHie (L mspan w) ]
+          ExpandedThingTc _ e
+            -> [ toHie (L mspan e) ]
+          ConLikeTc con _ _
+            -> [ toHie $ C Use $ L mspan $ conLikeName con ]
+          HsTick _ expr
+            -> [ toHie expr
+               ]
+          HsBinTick _ _ expr
+            -> [ toHie expr
+               ]
+          HsRecSelTc fld
+            -> [ toHie $ RFC RecFieldOcc Nothing (L mspan fld)
+               ]
+        HieRn -> case x of
+          HsRecSelRn fld
+            -> [ toHie $ RFC RecFieldOcc Nothing (L mspan fld)
+               ]
+          _ -> []
 
 -- NOTE: no longer have the location
 instance HiePass p => ToHie (HsTupArg (GhcPass p)) where
@@ -1505,23 +1509,17 @@ instance ( ToHie (RFContext label)
       ]
 
 instance HiePass p => ToHie (RFContext (LocatedA (FieldOcc (GhcPass p)))) where
-  toHie (RFC c rhs (L nspan f)) = concatM $ case f of
-    FieldOcc fld _ ->
-      case hiePass @p of
-        HieRn -> [toHie $ C (RecField c rhs) (L (locA nspan) fld)]
-        HieTc -> [toHie $ C (RecField c rhs) (L (locA nspan) fld)]
-
-instance HiePass p => ToHie (RFContext (LocatedA (AmbiguousFieldOcc (GhcPass p)))) where
-
-  toHie (RFC c rhs (L nspan afo)) = concatM $ case afo of
-    Unambiguous fld _ ->
-      case hiePass @p of
-        HieRn -> [toHie $ C (RecField c rhs) $ L (locA nspan) fld]
-        HieTc -> [toHie $ C (RecField c rhs) $ L (locA nspan) fld]
-    Ambiguous fld _ ->
-      case hiePass @p of
-        HieRn -> []
-        HieTc -> [ toHie $ C (RecField c rhs) (L (locA nspan) fld) ]
+  toHie (RFC c rhs (L nspan f)) = concatM $
+    case hiePass @p of
+      HieRn ->
+        case f of
+          FieldOcc _ fld ->
+            [toHie $ C (RecField c rhs) (L (locA nspan) $ unLoc fld)]
+      HieTc ->
+        case f of
+          FieldOcc _ fld ->
+            [toHie $ C (RecField c rhs) (L (locA nspan) $ unLoc fld)]
+
 
 instance HiePass p => ToHie (RScoped (ApplicativeArg (GhcPass p))) where
   toHie (RS sc (ApplicativeArgOne _ pat expr _)) = concatM
@@ -2107,10 +2105,10 @@ instance ToHie (LocatedA (DataFamInstDecl GhcRn)) where
 instance ToHie (LocatedA (TyFamInstDecl GhcRn)) where
   toHie (L sp (TyFamInstDecl _ d)) = toHie $ TS (ResolvedScopes [mkScope sp]) d
 
+
 instance HiePass p => ToHie (Context (FieldOcc (GhcPass p))) where
-  toHie (C c (FieldOcc n (L l _))) = case hiePass @p of
-    HieTc -> toHie (C c (L l n))
-    HieRn -> toHie (C c (L l n))
+  toHie (C c (FieldOcc _ l)) = toHie (C c l)
+  toHie (C _ (XFieldOcc _))  = concatM []
 
 instance HiePass p => ToHie (PatSynFieldContext (RecordPatSynField (GhcPass p))) where
   toHie (PSC sp (RecordPatSynField a b)) = concatM $
diff --git a/compiler/GHC/Parser/PostProcess.hs b/compiler/GHC/Parser/PostProcess.hs
index 854e113d32e..ec035542168 100644
--- a/compiler/GHC/Parser/PostProcess.hs
+++ b/compiler/GHC/Parser/PostProcess.hs
@@ -2913,7 +2913,7 @@ mkRdrRecordUpd overloaded_on exp@(L loc _) fbinds anns = do
     True -> do
       let qualifiedFields =
             [ L l lbl | L _ (HsFieldBind _ (L l lbl) _ _) <- fs'
-                      , isQual . ambiguousFieldOccRdrName $ lbl
+                      , isQual . fieldOccRdrName $ lbl
             ]
       case qualifiedFields of
           qf:_ -> addFatalError $ mkPlainErrorMsgEnvelope (getLocA qf) $
@@ -2959,7 +2959,7 @@ mk_rec_fields fs (Just s)  = HsRecFields { rec_ext = noExtField, rec_flds = fs
 
 mk_rec_upd_field :: HsRecField GhcPs (LHsExpr GhcPs) -> HsRecUpdField GhcPs GhcPs
 mk_rec_upd_field (HsFieldBind noAnn (L loc (FieldOcc _ rdr)) arg pun)
-  = HsFieldBind noAnn (L loc (Unambiguous noExtField rdr)) arg pun
+  = HsFieldBind noAnn (L loc (FieldOcc noExtField rdr)) arg pun
 
 mkInlinePragma :: SourceText -> (InlineSpec, RuleMatchInfo) -> Maybe Activation
                -> InlinePragma
@@ -3558,7 +3558,7 @@ mkRdrProjection :: NonEmpty (LocatedAn NoEpAnns (DotFieldOcc GhcPs)) -> AnnProje
 mkRdrProjection flds anns =
   HsProjection {
       proj_ext = anns
-    , proj_flds = flds
+    , proj_flds = fmap unLoc flds
     }
 
 mkRdrProjUpdate :: SrcSpanAnnA -> Located [LocatedAn NoEpAnns (DotFieldOcc GhcPs)]
diff --git a/compiler/GHC/Rename/Bind.hs b/compiler/GHC/Rename/Bind.hs
index 85984a58607..3fef3acac9d 100644
--- a/compiler/GHC/Rename/Bind.hs
+++ b/compiler/GHC/Rename/Bind.hs
@@ -824,7 +824,7 @@ rnPatSynBind sig_fn bind@(PSB { psb_id = L l name
                           , psb_ext = fvs' }
               selector_names = case details' of
                                  RecCon names ->
-                                  map (foExt . recordPatSynField) names
+                                      map (unLoc . foLabel . recordPatSynField) names
                                  _ -> []
 
         ; fvs' `seq` -- See Note [Free-variable space leak]
diff --git a/compiler/GHC/Rename/Env.hs b/compiler/GHC/Rename/Env.hs
index d7473d8386c..73ddb9242a4 100644
--- a/compiler/GHC/Rename/Env.hs
+++ b/compiler/GHC/Rename/Env.hs
@@ -1525,8 +1525,8 @@ lookupGlobalOccRn_overloaded rdr_name =
               addNameClashErrRn rdr_name gres
               return (Just gre) }
 
-getFieldUpdLbl :: LHsRecUpdField (GhcPass p) q -> LocatedN RdrName
-getFieldUpdLbl = ambiguousFieldOccLRdrName . unLoc . hfbLHS . unLoc
+getFieldUpdLbl :: IsPass p => LHsRecUpdField (GhcPass p) q -> LocatedN RdrName
+getFieldUpdLbl = fieldOccLRdrName . unLoc . hfbLHS . unLoc
 
 -- | Returns all possible collections of field labels for the given
 -- record update.
@@ -1620,10 +1620,10 @@ lookupRecUpdFields flds
 *                                                                      *
 **********************************************************************-}
 
-getUpdFieldLbls :: forall p q. UnXRec (GhcPass p)
+getUpdFieldLbls :: forall p q. IsPass p
                 => [LHsRecUpdField (GhcPass p) q] -> [RdrName]
 getUpdFieldLbls
-  = map $ ambiguousFieldOccRdrName
+  = map $ fieldOccRdrName
         . unXRec @(GhcPass p)
         . hfbLHS
         . unXRec @(GhcPass p)
diff --git a/compiler/GHC/Rename/Expr.hs b/compiler/GHC/Rename/Expr.hs
index 41c6a7ccbf6..aa0ea197c38 100644
--- a/compiler/GHC/Rename/Expr.hs
+++ b/compiler/GHC/Rename/Expr.hs
@@ -339,7 +339,7 @@ rnExpr (HsVar _ (L l v))
                   ; this_mod <- getModule
                   ; when (nameIsLocalOrFrom this_mod sel_name) $
                       checkThLocalName sel_name
-                  ; return (HsRecSel noExtField (FieldOcc sel_name (L l v) ), unitFV sel_name)
+                  ; return (XExpr (HsRecSelRn (FieldOcc v  (L l sel_name))), unitFV sel_name)
                   }
             | nm == nilDataConName
               -- Treat [] as an ExplicitList, so that
@@ -416,8 +416,8 @@ rnExpr (OpApp _ e1 op e2)
         -- more, so I've removed the test.  Adding HsPars in GHC.Tc.Deriv.Generate
         -- should prevent bad things happening.
         ; fixity <- case op' of
-              L _ (HsVar _ (L _ n)) -> lookupFixityRn n
-              L _ (HsRecSel _ f)    -> lookupFieldFixityRn f
+              L _ (HsVar _ (L _ n))      -> lookupFixityRn n
+              L _ (XExpr (HsRecSelRn f)) -> lookupFieldFixityRn f
               _ -> return (Fixity minPrecedence InfixL)
                    -- c.f. lookupFixity for unbound
 
@@ -439,7 +439,7 @@ rnExpr (NegApp _ e _)
 rnExpr (HsGetField _ e f)
  = do { (getField, fv_getField) <- lookupSyntaxName getFieldName
       ; (e, fv_e) <- rnLExpr e
-      ; let f' = rnDotFieldOcc f
+      ; let f' = rnDotFieldOcc <$> f
       ; return ( mkExpandedExpr
                    (HsGetField noExtField e f')
                    (mkGetField getField e (fmap (unLoc . dfoLabel) f'))
@@ -448,10 +448,10 @@ rnExpr (HsGetField _ e f)
 rnExpr (HsProjection _ fs)
   = do { (getField, fv_getField) <- lookupSyntaxName getFieldName
        ; circ <- lookupOccRn compose_RDR
-       ; let fs' = fmap rnDotFieldOcc fs
+       ; let fs' = NE.map rnDotFieldOcc fs
        ; return ( mkExpandedExpr
                     (HsProjection noExtField fs')
-                    (mkProjection getField circ (fmap (fmap (unLoc . dfoLabel)) fs'))
+                    (mkProjection getField circ $ NE.map (unLoc . dfoLabel) fs')
                 , unitFV circ `plusFV` fv_getField) }
 
 ------------------------------------------
@@ -588,7 +588,6 @@ rnExpr (RecordUpd { rupd_expr = L l expr, rupd_flds = rbinds })
                          (mkRecordDotUpd getField setField (L l e) us)
                         , plusFVs [fv_getField, fv_setField, fv_e, fv_us] ) }
 
-rnExpr (HsRecSel x _) = dataConCantHappen x
 
 rnExpr (ExprWithTySig _ expr pty)
   = do  { (pty', fvTy)    <- rnHsSigWcType ExprWithTySigCtx pty
@@ -890,11 +889,11 @@ However we can still defer this error completely, and we do defer it if
 ************************************************************************
 -}
 
-rnDotFieldOcc :: LocatedAn NoEpAnns (DotFieldOcc GhcPs) -> LocatedAn NoEpAnns (DotFieldOcc GhcRn)
-rnDotFieldOcc (L l (DotFieldOcc x label)) = L l (DotFieldOcc x label)
+rnDotFieldOcc :: DotFieldOcc GhcPs ->  DotFieldOcc GhcRn
+rnDotFieldOcc (DotFieldOcc x label) = DotFieldOcc x label
 
 rnFieldLabelStrings :: FieldLabelStrings GhcPs -> FieldLabelStrings GhcRn
-rnFieldLabelStrings (FieldLabelStrings fls) = FieldLabelStrings (map rnDotFieldOcc fls)
+rnFieldLabelStrings (FieldLabelStrings fls) = FieldLabelStrings (map (fmap rnDotFieldOcc) fls)
 
 {-
 ************************************************************************
@@ -2864,14 +2863,14 @@ mkSet set_field acc (field, g) = wrapGenSpan (mkSetField set_field g field acc)
 -- mkProjection fields calculates a projection.
 -- e.g. .x = mkProjection [x] = getField @"x"
 --      .x.y = mkProjection [.x, .y] = (.y) . (.x) = getField @"y" . getField @"x"
-mkProjection :: Name -> Name -> NonEmpty (LocatedAn NoEpAnns FieldLabelString) -> HsExpr GhcRn
+mkProjection :: Name -> Name -> NonEmpty FieldLabelString -> HsExpr GhcRn
 mkProjection getFieldName circName (field :| fields) = foldl' f (proj field) fields
   where
-    f :: HsExpr GhcRn -> LocatedAn NoEpAnns FieldLabelString -> HsExpr GhcRn
+    f :: HsExpr GhcRn -> FieldLabelString -> HsExpr GhcRn
     f acc field = genHsApps circName $ map wrapGenSpan [proj field, acc]
 
-    proj :: LocatedAn NoEpAnns FieldLabelString -> HsExpr GhcRn
-    proj (L _ (FieldLabelString f)) = genHsVar getFieldName `genAppType` genHsTyLit f
+    proj :: FieldLabelString -> HsExpr GhcRn
+    proj (FieldLabelString f) = genHsVar getFieldName `genAppType` genHsTyLit f
 
 -- mkProjUpdateSetField calculates functions representing dot notation record updates.
 -- e.g. Suppose an update like foo.bar = 1.
diff --git a/compiler/GHC/Rename/Fixity.hs b/compiler/GHC/Rename/Fixity.hs
index 7ddf9fe6fb8..ce0ee3b3173 100644
--- a/compiler/GHC/Rename/Fixity.hs
+++ b/compiler/GHC/Rename/Fixity.hs
@@ -202,4 +202,4 @@ lookupTyFixityRn :: LocatedN Name -> RnM Fixity
 lookupTyFixityRn = lookupFixityRn . unLoc
 
 lookupFieldFixityRn :: FieldOcc GhcRn -> RnM Fixity
-lookupFieldFixityRn (FieldOcc n _) = lookupFixityRn n
+lookupFieldFixityRn (FieldOcc _ n) = lookupFixityRn (unLoc n)
diff --git a/compiler/GHC/Rename/HsType.hs b/compiler/GHC/Rename/HsType.hs
index 7d1fa013b28..d1b5fcb88eb 100644
--- a/compiler/GHC/Rename/HsType.hs
+++ b/compiler/GHC/Rename/HsType.hs
@@ -1341,7 +1341,7 @@ rnField fl_env env (L l (ConDeclField _ names ty haddock_doc))
 
 lookupField :: FastStringEnv FieldLabel -> FieldOcc GhcPs -> FieldOcc GhcRn
 lookupField fl_env (FieldOcc _ (L lr rdr)) =
-    FieldOcc sel (L lr $ mkRdrUnqual $ occName sel)
+    FieldOcc (mkRdrUnqual $ occName sel) (L lr sel)
   where
     lbl = occNameFS $ rdrNameOcc rdr
     sel = flSelector
@@ -1467,10 +1467,10 @@ data NegationHandling = ReassociateNegation | KeepNegationIntact
 get_op :: LHsExpr GhcRn -> OpName
 -- An unbound name could be either HsVar or HsUnboundVar
 -- See GHC.Rename.Expr.rnUnboundVar
-get_op (L _ (HsVar _ n))         = NormalOp (unLoc n)
-get_op (L _ (HsUnboundVar _ uv)) = UnboundOp uv
-get_op (L _ (HsRecSel _ fld))    = RecFldOp fld
-get_op other                     = pprPanic "get_op" (ppr other)
+get_op (L _ (HsVar _ n))                 = NormalOp (unLoc n)
+get_op (L _ (HsUnboundVar _ uv))         = UnboundOp uv
+get_op (L _ (XExpr (HsRecSelRn fld)))    = RecFldOp fld
+get_op other                             = pprPanic "get_op" (ppr other)
 
 -- Parser left-associates everything, but
 -- derived instances may have correctly-associated things to
@@ -1610,7 +1610,6 @@ lookupFixityOp NegateOp      = lookupFixityRn negateName
 lookupFixityOp (UnboundOp u) = lookupFixityRn (mkUnboundName (occName u))
 lookupFixityOp (RecFldOp f)  = lookupFieldFixityRn f
 
-
 -- Precedence-related error messages
 
 precParseErr :: (OpName,Fixity) -> (OpName,Fixity) -> RnM ()
diff --git a/compiler/GHC/Rename/Pat.hs b/compiler/GHC/Rename/Pat.hs
index 170d1004178..162dc4e0d16 100644
--- a/compiler/GHC/Rename/Pat.hs
+++ b/compiler/GHC/Rename/Pat.hs
@@ -10,6 +10,8 @@
 {-# LANGUAGE MultiWayIf                 #-}
 {-# LANGUAGE DerivingStrategies         #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
+{-# HLINT ignore "Use camelCase" #-}
 
 {-
 (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
@@ -880,7 +882,7 @@ rnHsRecFields ctxt mk_arg (HsRecFields { rec_flds = flds, rec_dotdot = dotdot })
            ; return $ L l $
                HsFieldBind
                  { hfbAnn = noAnn
-                 , hfbLHS = L loc (FieldOcc sel (L ll arg_rdr))
+                 , hfbLHS = L loc (FieldOcc arg_rdr (L ll sel))
                  , hfbRHS = arg'
                  , hfbPun = pun } }
 
@@ -888,7 +890,7 @@ rnHsRecFields ctxt mk_arg (HsRecFields { rec_flds = flds, rec_dotdot = dotdot })
               -> Maybe Name -- The constructor (Nothing for an
                                 --    out of scope constructor)
               -> [LHsRecField GhcRn (LocatedA arg)] -- Explicit fields
-              -> RnM ([LHsRecField GhcRn (LocatedA arg)])   -- Field Labels we need to fill in
+              -> RnM [LHsRecField GhcRn (LocatedA arg)]   -- Field Labels we need to fill in
     rn_dotdot (Just (L loc_e (RecFieldsDotDot n))) (Just con) flds -- ".." on record construction / pat match
       | not (isUnboundName con) -- This test is because if the constructor
                                 -- isn't in scope the constructor lookup will add
@@ -900,7 +902,7 @@ rnHsRecFields ctxt mk_arg (HsRecFields { rec_flds = flds, rec_dotdot = dotdot })
            ; (rdr_env, lcl_env) <- getRdrEnvs
            ; conInfo <- lookupConstructorInfo con
            ; when (conFieldInfo conInfo == ConHasPositionalArgs) (addErr (TcRnIllegalWildcardsInConstructor con))
-           ; let present_flds = mkOccSet $ map rdrNameOcc (getFieldLbls flds)
+           ; let present_flds = mkOccSet $ map rdrNameOcc (getFieldRdrs flds)
 
                    -- For constructor uses (but not patterns)
                    -- the arg should be in scope locally;
@@ -926,7 +928,7 @@ rnHsRecFields ctxt mk_arg (HsRecFields { rec_flds = flds, rec_dotdot = dotdot })
            ; return [ L (noAnnSrcSpan loc) (HsFieldBind
                         { hfbAnn = noAnn
                         , hfbLHS
-                           = L (noAnnSrcSpan loc) (FieldOcc sel (L (noAnnSrcSpan loc) arg_rdr))
+                           = L (noAnnSrcSpan loc) (FieldOcc arg_rdr (L (noAnnSrcSpan loc) sel))
                         , hfbRHS = L locn (mk_arg loc arg_rdr)
                         , hfbPun = False })
                     | fl <- dot_dot_fields
@@ -1016,10 +1018,10 @@ rnHsRecUpdFields flds
               -> RnM ([LHsRecUpdField GhcRn GhcRn], FreeVars)
       rn_flds _ _ [] = return ([], emptyFVs)
       rn_flds pun_ok mb_unambig_lbls
-              ((L l (HsFieldBind { hfbLHS = L loc f
+              ((L l (HsFieldBind { hfbLHS = L loc (FieldOcc _ f)
                                  , hfbRHS = arg
                                  , hfbPun = pun })):flds)
-        = do { let lbl = ambiguousFieldOccRdrName f
+        = do { let lbl = unLoc f
              ; (arg' :: LHsExpr GhcPs) <- if pun
                        then do { setSrcSpanA loc $
                                  checkErr pun_ok (TcRnIllegalFieldPunning (L (locA loc) lbl))
@@ -1028,15 +1030,18 @@ rnHsRecUpdFields flds
                                ; return (L (l2l loc) (HsVar noExtField (L (l2l loc) arg_rdr))) }
                        else return arg
              ; (arg'', fvs) <- rnLExpr arg'
-             ; let lbl' :: AmbiguousFieldOcc GhcRn
+             ; let lbl' :: FieldOcc GhcRn
                    lbl' = case mb_unambig_lbls of
                             { Just (fl:_) ->
                                 let sel_name = flSelector fl
-                                in Unambiguous sel_name   (L (l2l loc) lbl)
-                            ; _ ->   Ambiguous noExtField (L (l2l loc) lbl) }
+                                in FieldOcc lbl (L (l2l loc) sel_name)
+                                -- We have one last chance to be disambiguated during type checking.
+                                -- At least, until type-directed disambiguation stops being supported.
+                                -- see note [Ambiguous FieldOcc in record updates] for more info.
+                            ; _ -> FieldOcc lbl (L (l2l loc) (mkUnboundName $ rdrNameOcc lbl)) }
                    fld' :: LHsRecUpdField GhcRn GhcRn
                    fld' = L l (HsFieldBind { hfbAnn = noAnn
-                                           , hfbLHS = L loc lbl'
+                                           , hfbLHS = L (l2l loc) lbl'
                                            , hfbRHS = arg''
                                            , hfbPun = pun })
              ; (flds', fvs') <- rn_flds pun_ok (tail <$> mb_unambig_lbls) flds
@@ -1045,9 +1050,11 @@ rnHsRecUpdFields flds
 getFieldIds :: [LHsRecField GhcRn arg] -> [Name]
 getFieldIds flds = map (hsRecFieldSel . unLoc) flds
 
-getFieldLbls :: forall p arg . UnXRec p => [LHsRecField p arg] -> [RdrName]
-getFieldLbls flds
-  = map (unXRec @p . foLabel . unXRec @p . hfbLHS . unXRec @p) flds
+getFieldRdrs :: [LHsRecField GhcRn arg] -> [RdrName]
+getFieldRdrs flds = map (foExt . unXRec @GhcRn . hfbLHS . unLoc) flds
+
+getFieldLbls :: forall p arg . UnXRec p => [LHsRecField p arg] -> [IdP p]
+getFieldLbls = map (unXRec @p . foLabel . unXRec @p . hfbLHS . unXRec @p)
 
 needFlagDotDot :: HsRecFieldContext -> TcRnMessage
 needFlagDotDot = TcRnIllegalWildcardsInRecord . toRecordFieldPart
diff --git a/compiler/GHC/Tc/Gen/Expr.hs b/compiler/GHC/Tc/Gen/Expr.hs
index 4054269348a..59ee46889f9 100644
--- a/compiler/GHC/Tc/Gen/Expr.hs
+++ b/compiler/GHC/Tc/Gen/Expr.hs
@@ -293,7 +293,6 @@ tcExpr e@(HsApp {})              res_ty = tcApp e res_ty
 tcExpr e@(OpApp {})              res_ty = tcApp e res_ty
 tcExpr e@(HsAppType {})          res_ty = tcApp e res_ty
 tcExpr e@(ExprWithTySig {})      res_ty = tcApp e res_ty
-tcExpr e@(HsRecSel {})           res_ty = tcApp e res_ty
 
 tcExpr (XExpr e)                 res_ty = tcXExpr e res_ty
 
@@ -738,7 +737,6 @@ tcXExpr xe@(ExpandedThingRn o e') res_ty
   | OrigStmt ls@(L loc _) <- o
   = setSrcSpanA loc $
        mkExpandedStmtTc ls <$> tcApp (XExpr xe) res_ty
-
 tcXExpr xe res_ty = tcApp (XExpr xe) res_ty
 
 {-
@@ -1300,11 +1298,10 @@ expandRecordUpd record_expr possible_parents rbnds res_ty
        -- See Note [Disambiguating record updates] in GHC.Rename.Pat.
        ; (cons, rbinds)
            <- disambiguateRecordBinds record_expr record_rho possible_parents rbnds res_ty
-       ; let upd_flds = map (unLoc . hfbLHS . unLoc) rbinds
-             sel_ids      = map selectorAmbiguousFieldOcc upd_flds
+       ; let sel_ids       = map (unLoc . foLabel . unLoc . hfbLHS . unLoc) rbinds
              upd_fld_names = map idName sel_ids
              relevant_cons = nonDetEltsUniqSet cons
-             relevant_con = head relevant_cons
+             relevant_con  = head relevant_cons
 
       -- STEP 2: expand the record update.
       --
@@ -1584,7 +1581,7 @@ disambiguateRecordBinds record_expr record_rho possible_parents rbnds res_ty
                 -> TcM (LHsRecUpdField GhcTc GhcRn)
     lookupField fld_gre (L l upd)
       = do { let L loc af = hfbLHS upd
-                 lbl      = ambiguousFieldOccRdrName af
+                 lbl      = fieldOccRdrName af
                  mb_gre   = pickGREs lbl [fld_gre]
                       -- NB: this GRE can be 'Nothing' when in GHCi.
                       -- See test T10439.
@@ -1596,7 +1593,7 @@ disambiguateRecordBinds record_expr record_rho possible_parents rbnds res_ty
            ; sel <- tcLookupId (greName fld_gre)
            ; return $ L l HsFieldBind
                { hfbAnn = hfbAnn upd
-               , hfbLHS = L (l2l loc) $ Unambiguous sel (L (l2l loc) lbl)
+               , hfbLHS = L (l2l loc) (FieldOcc lbl  (L (l2l loc) sel))
                , hfbRHS = hfbRHS upd
                , hfbPun = hfbPun upd
                } }
@@ -1669,11 +1666,11 @@ fieldCtxt field_name
 tcRecordField :: ConLike -> Assoc Name Type
               -> LFieldOcc GhcRn -> LHsExpr GhcRn
               -> TcM (Maybe (LFieldOcc GhcTc, LHsExpr GhcTc))
-tcRecordField con_like flds_w_tys (L loc (FieldOcc sel_name lbl)) rhs
+tcRecordField con_like flds_w_tys (L loc (FieldOcc rdr (L l sel_name))) rhs
   | Just field_ty <- assocMaybe flds_w_tys sel_name
       = addErrCtxt (fieldCtxt field_lbl) $
         do { rhs' <- tcCheckPolyExprNC rhs field_ty
-           ; hasFixedRuntimeRep_syntactic (FRRRecordCon (unLoc lbl) (unLoc rhs'))
+           ; hasFixedRuntimeRep_syntactic (FRRRecordCon rdr (unLoc rhs'))
                 field_ty
            ; let field_id = mkUserLocal (nameOccName sel_name)
                                         (nameUnique sel_name)
@@ -1682,12 +1679,12 @@ tcRecordField con_like flds_w_tys (L loc (FieldOcc sel_name lbl)) rhs
                 --          (so we can find it easily)
                 --      but is a LocalId with the appropriate type of the RHS
                 --          (so the expansion knows the type of local binder to make)
-           ; return (Just (L loc (FieldOcc field_id lbl), rhs')) }
+           ; return (Just (L loc (FieldOcc rdr (L l field_id)), rhs')) }
       | otherwise
       = do { addErrTc (badFieldConErr (getName con_like) field_lbl)
            ; return Nothing }
   where
-        field_lbl = FieldLabelString $ occNameFS $ rdrNameOcc (unLoc lbl)
+        field_lbl = FieldLabelString $ occNameFS $ rdrNameOcc rdr
 
 
 checkMissingFields ::  ConLike -> HsRecordBinds GhcRn -> [Scaled TcType] -> TcM ()
diff --git a/compiler/GHC/Tc/Gen/Head.hs b/compiler/GHC/Tc/Gen/Head.hs
index 882661c969c..c10a326d2e0 100644
--- a/compiler/GHC/Tc/Gen/Head.hs
+++ b/compiler/GHC/Tc/Gen/Head.hs
@@ -567,7 +567,7 @@ tcInferAppHead_maybe :: HsExpr GhcRn
 tcInferAppHead_maybe fun
   = case fun of
       HsVar _ (L _ nm)          -> Just <$> tcInferId nm
-      HsRecSel _ f              -> Just <$> tcInferRecSelId f
+      XExpr (HsRecSelRn f)      -> Just <$> tcInferRecSelId f
       ExprWithTySig _ e hs_ty   -> Just <$> tcExprWithSig e hs_ty
       HsOverLit _ lit           -> Just <$> tcInferOverLit lit
       _                         -> return Nothing
@@ -596,16 +596,15 @@ addHeadCtxt fun_ctxt thing_inside
 ********************************************************************* -}
 
 tcInferRecSelId :: FieldOcc GhcRn
-                -> TcM (HsExpr GhcTc, TcSigmaType)
-tcInferRecSelId (FieldOcc sel_name lbl)
-   = do { sel_id <- tc_rec_sel_id
-        ; let expr = HsRecSel noExtField (FieldOcc sel_id lbl)
-        ; return (expr, idType sel_id)
+                -> TcM ( (HsExpr GhcTc, TcSigmaType))
+tcInferRecSelId (FieldOcc lbl (L l sel_name))
+     = do { sel_id <- tc_rec_sel_id
+        ; let expr = XExpr (HsRecSelTc (FieldOcc lbl (L l sel_id)))
+        ; return $ (expr, idType sel_id)
         }
      where
        occ :: OccName
-       occ = rdrNameOcc (unLoc lbl)
-
+       occ = nameOccName sel_name
        tc_rec_sel_id :: TcM TcId
        -- Like tc_infer_id, but returns an Id not a HsExpr,
        -- so we can wrap it back up into a HsRecSel
diff --git a/compiler/GHC/Tc/Gen/Pat.hs b/compiler/GHC/Tc/Gen/Pat.hs
index 8cd2a2b2732..aaf478d9a94 100644
--- a/compiler/GHC/Tc/Gen/Pat.hs
+++ b/compiler/GHC/Tc/Gen/Pat.hs
@@ -1648,14 +1648,14 @@ tcConValArgs con_like arg_tys penv con_args thing_inside = case con_args of
     where
       tc_field :: Checker (LHsRecField GhcRn (LPat GhcRn))
                           (LHsRecField GhcTc (LPat GhcTc))
-      tc_field penv
-               (L l (HsFieldBind ann (L loc (FieldOcc sel (L lr rdr))) pat pun))
-               thing_inside
+      tc_field  penv
+                (L l (HsFieldBind ann (L loc (FieldOcc rdr (L lr sel))) pat pun))
+                thing_inside
         = do { sel'   <- tcLookupId sel
              ; pat_ty <- setSrcSpanA loc $ find_field_ty sel
                                             (occNameFS $ rdrNameOcc rdr)
              ; (pat', res) <- tcConArg penv (pat, pat_ty) thing_inside
-             ; return (L l (HsFieldBind ann (L loc (FieldOcc sel' (L lr rdr))) pat'
+             ; return (L l (HsFieldBind ann (L loc (FieldOcc rdr (L lr sel'))) pat'
                                                                         pun), res) }
       -- See Note [Omitted record fields and linearity]
       check_omitted_fields_multiplicity :: TcM MultiplicityCheckCoercions
@@ -1685,7 +1685,7 @@ tcConValArgs con_like arg_tys penv con_args thing_inside = case con_args of
       (bound_field_tys, omitted_field_tys) = partition is_bound all_field_tys
 
       is_bound :: (Maybe FieldLabel, Scaled TcType) -> Bool
-      is_bound (Just fl, _) = elem (flSelector fl) (map (\(L _ (HsFieldBind _ (L _ (FieldOcc sel _ )) _ _)) -> sel) rpats)
+      is_bound (Just fl, _) = elem (flSelector fl) (map (\(L _ (HsFieldBind _ (L _ (FieldOcc _ sel )) _ _)) -> unLoc sel) rpats)
       is_bound _ = False
 
       all_field_tys :: [(Maybe FieldLabel, Scaled TcType)]
diff --git a/compiler/GHC/Tc/TyCl/Utils.hs b/compiler/GHC/Tc/TyCl/Utils.hs
index 4433839b437..a679e063c96 100644
--- a/compiler/GHC/Tc/TyCl/Utils.hs
+++ b/compiler/GHC/Tc/TyCl/Utils.hs
@@ -942,8 +942,7 @@ mkOneRecordSelector all_cons idDetails fl has_sel
     rec_field  = noLocA (HsFieldBind
                         { hfbAnn = noAnn
                         , hfbLHS
-                           = L locc (FieldOcc sel_name
-                                      (L locn $ mkRdrUnqual (nameOccName sel_name)))
+                           = L locc (FieldOcc (mkRdrUnqual $ nameOccName sel_name) (L locn sel_name))
                         , hfbRHS
                            = L loc' (VarPat noExtField (L locn field_var))
                         , hfbPun = False })
diff --git a/compiler/GHC/Tc/Types/Origin.hs b/compiler/GHC/Tc/Types/Origin.hs
index cae7d9f22ab..22062f47e46 100644
--- a/compiler/GHC/Tc/Types/Origin.hs
+++ b/compiler/GHC/Tc/Types/Origin.hs
@@ -718,7 +718,6 @@ exprCtOrigin :: HsExpr GhcRn -> CtOrigin
 exprCtOrigin (HsVar _ (L _ name)) = OccurrenceOf name
 exprCtOrigin (HsGetField _ _ (L _ f)) = HasFieldOrigin (field_label $ unLoc $ dfoLabel f)
 exprCtOrigin (HsUnboundVar {})    = Shouldn'tHappenOrigin "unbound variable"
-exprCtOrigin (HsRecSel _ f)       = OccurrenceOfRecSel (unLoc $ foLabel f)
 exprCtOrigin (HsOverLabel _ l)  = OverLabelOrigin l
 exprCtOrigin (ExplicitList {})    = ListOrigin
 exprCtOrigin (HsIPVar _ ip)       = IPOccOrigin ip
@@ -759,6 +758,7 @@ exprCtOrigin (XExpr (ExpandedThingRn thing _)) | OrigExpr a <- thing = exprCtOri
                                                | OrigStmt _ <- thing = DoOrigin
                                                | OrigPat p  <- thing = DoPatOrigin p
 exprCtOrigin (XExpr (PopErrCtxt {})) = Shouldn'tHappenOrigin "PopErrCtxt"
+exprCtOrigin (XExpr (HsRecSelRn f))  = OccurrenceOfRecSel (foExt f)
 
 -- | Extract a suitable CtOrigin from a MatchGroup
 matchesCtOrigin :: MatchGroup GhcRn (LHsExpr GhcRn) -> CtOrigin
diff --git a/compiler/GHC/Tc/Zonk/Type.hs b/compiler/GHC/Tc/Zonk/Type.hs
index 5611a9de50f..27c92628f7c 100644
--- a/compiler/GHC/Tc/Zonk/Type.hs
+++ b/compiler/GHC/Tc/Zonk/Type.hs
@@ -608,8 +608,8 @@ zonkTopBndrs :: [TcId] -> TcM [Id]
 zonkTopBndrs ids = initZonkEnv DefaultFlexi $ zonkIdBndrs ids
 
 zonkFieldOcc :: FieldOcc GhcTc -> ZonkTcM (FieldOcc GhcTc)
-zonkFieldOcc (FieldOcc sel lbl)
-  = fmap ((flip FieldOcc) lbl) $ zonkIdBndr sel
+zonkFieldOcc (FieldOcc lbl (L l sel))
+  = FieldOcc lbl . L l <$> zonkIdBndr sel
 
 zonkEvBndrsX :: [EvVar] -> ZonkBndrTcM [EvVar]
 zonkEvBndrsX = traverse zonkEvBndrX
@@ -935,9 +935,6 @@ zonkExpr (HsUnboundVar her occ)
            ty'  <- zonkTcTypeToTypeX ty
            return (HER ref ty' u)
 
-zonkExpr (HsRecSel _ (FieldOcc v occ))
-  = do { v' <- zonkIdOcc v
-       ; return (HsRecSel noExtField (FieldOcc v' occ)) }
 
 zonkExpr (HsIPVar x _) = dataConCantHappen x
 
@@ -1098,6 +1095,10 @@ zonkExpr (XExpr (ConLikeTc con tvs tys))
     -- The tvs come straight from the data-con, and so are strictly redundant
     -- See Wrinkles of Note [Typechecking data constructors] in GHC.Tc.Gen.Head
 
+zonkExpr (XExpr (HsRecSelTc (FieldOcc occ (L l v))))
+  = do { v' <- zonkIdOcc v
+       ; return (XExpr (HsRecSelTc (FieldOcc occ (L l v')))) }
+
 zonkExpr (RecordUpd x _ _)  = dataConCantHappen x
 zonkExpr (HsGetField x _ _) = dataConCantHappen x
 zonkExpr (HsProjection x _) = dataConCantHappen x
diff --git a/compiler/GHC/ThToHs.hs b/compiler/GHC/ThToHs.hs
index 248e9b002d1..499a90f2958 100644
--- a/compiler/GHC/ThToHs.hs
+++ b/compiler/GHC/ThToHs.hs
@@ -1159,7 +1159,7 @@ cvtl e = wrapLA (cvt e)
                               ; return $ mkRdrRecordCon c' (HsRecFields noExtField flds' Nothing) noAnn }
     cvt (RecUpdE e flds) = do { e' <- cvtl e
                               ; flds'
-                                  <- mapM (cvtFld (wrapParLA mkAmbiguousFieldOcc))
+                                  <- mapM (cvtFld (wrapParLA mkFieldOcc))
                                            flds
                               ; return $ RecordUpd noAnn e' $
                                          RegularRecUpdFields
@@ -1177,7 +1177,7 @@ cvtl e = wrapLA (cvt e)
                                ; return $ HsGetField noExtField e'
                                          (L noSrcSpanA (DotFieldOcc noAnn (L noSrcSpanA (FieldLabelString (fsLit f))))) }
     cvt (ProjectionE xs) = return $ HsProjection noAnn $ fmap
-                                         (L noSrcSpanA . DotFieldOcc noAnn . L noSrcSpanA . FieldLabelString  . fsLit) xs
+                                         (DotFieldOcc noAnn . L noSrcSpanA . FieldLabelString  . fsLit) xs
     cvt (TypedSpliceE e) = do { e' <- parenthesizeHsExpr appPrec <$> cvtl e
                               ; return $ HsTypedSplice noAnn e' }
     cvt (TypedBracketE e) = do { e' <- cvtl e
diff --git a/compiler/Language/Haskell/Syntax/Expr.hs b/compiler/Language/Haskell/Syntax/Expr.hs
index ea958085bbe..e7fcaa62dc1 100644
--- a/compiler/Language/Haskell/Syntax/Expr.hs
+++ b/compiler/Language/Haskell/Syntax/Expr.hs
@@ -351,10 +351,6 @@ data HsExpr p
                              --   solving. See Note [Holes] in GHC.Tc.Types.Constraint.
 
 
-  | HsRecSel  (XRecSel p)
-              (FieldOcc p) -- ^ Variable pointing to record selector
-                           -- See Note [Non-overloaded record field selectors] and
-                           -- Note [Record selectors in the AST]
 
   | HsOverLabel (XOverLabel p) FastString
      -- ^ Overloaded label (Note [Overloaded labels] in GHC.OverloadedLabels)
@@ -573,7 +569,7 @@ data HsExpr p
   -- For details on above see Note [exact print annotations] in GHC.Parser.Annotation
   | HsProjection {
         proj_ext :: XProjection p
-      , proj_flds :: NonEmpty (XRec p (DotFieldOcc p))
+      , proj_flds :: NonEmpty (DotFieldOcc p)
       }
 
   -- | Expression with an explicit type signature. @e :: type@
diff --git a/compiler/Language/Haskell/Syntax/Extension.hs b/compiler/Language/Haskell/Syntax/Extension.hs
index e7f583c71e2..67e1d50db0c 100644
--- a/compiler/Language/Haskell/Syntax/Extension.hs
+++ b/compiler/Language/Haskell/Syntax/Extension.hs
@@ -467,13 +467,6 @@ type family XXDotFieldOcc  x
 type family XSCC            x
 type family XXPragE         x
 
-
--- -------------------------------------
--- AmbiguousFieldOcc type families
-type family XUnambiguous        x
-type family XAmbiguous          x
-type family XXAmbiguousFieldOcc x
-
 -- -------------------------------------
 -- HsTupArg type families
 type family XPresent  x
diff --git a/compiler/Language/Haskell/Syntax/Pat.hs b/compiler/Language/Haskell/Syntax/Pat.hs
index 4c04e70d2eb..20d2f659ae1 100644
--- a/compiler/Language/Haskell/Syntax/Pat.hs
+++ b/compiler/Language/Haskell/Syntax/Pat.hs
@@ -319,14 +319,14 @@ type LHsFieldBind p id arg = XRec p (HsFieldBind id arg)
 -- | Located Haskell Record Field
 type LHsRecField  p arg = XRec p (HsRecField  p arg)
 
--- | Located Haskell Record Update Field
-type LHsRecUpdField p q = XRec p (HsRecUpdField p q)
-
 -- | Haskell Record Field
 type HsRecField p arg   = HsFieldBind (LFieldOcc p) arg
 
+-- | Located Haskell Record Update Field
+type LHsRecUpdField p q = XRec p (HsRecUpdField p q)
+
 -- | Haskell Record Update Field
-type HsRecUpdField p q  = HsFieldBind (LAmbiguousFieldOcc p) (LHsExpr q)
+type HsRecUpdField p q  = HsFieldBind (LFieldOcc p) (LHsExpr q)
 
 -- | Haskell Field Binding
 --
@@ -395,11 +395,11 @@ data HsFieldBind lhs rhs = HsFieldBind {
 --
 -- See also Note [Disambiguating record updates] in GHC.Rename.Pat.
 
-hsRecFields :: forall p arg.UnXRec p => HsRecFields p arg -> [XCFieldOcc p]
+hsRecFields :: forall p arg.UnXRec p => HsRecFields p arg -> [IdP p]
 hsRecFields rbinds = Data.List.map (hsRecFieldSel . unXRec @p) (rec_flds rbinds)
 
 hsRecFieldsArgs :: forall p arg. UnXRec p => HsRecFields p arg -> [arg]
 hsRecFieldsArgs rbinds = Data.List.map (hfbRHS . unXRec @p) (rec_flds rbinds)
 
-hsRecFieldSel :: forall p arg. UnXRec p => HsRecField p arg -> XCFieldOcc p
-hsRecFieldSel = foExt . unXRec @p . hfbLHS
+hsRecFieldSel :: forall p arg. UnXRec p => HsRecField p arg -> IdP p
+hsRecFieldSel = unXRec @p . foLabel . unXRec @p . hfbLHS
diff --git a/compiler/Language/Haskell/Syntax/Type.hs b/compiler/Language/Haskell/Syntax/Type.hs
index bff2909bf5b..d283b8dc34f 100644
--- a/compiler/Language/Haskell/Syntax/Type.hs
+++ b/compiler/Language/Haskell/Syntax/Type.hs
@@ -55,7 +55,6 @@ module Language.Haskell.Syntax.Type (
         HsConDetails(..), noTypeArgs,
 
         FieldOcc(..), LFieldOcc,
-        AmbiguousFieldOcc(..), LAmbiguousFieldOcc,
 
         mapHsOuterImplicit,
         hsQTvExplicit,
@@ -69,7 +68,6 @@ import Language.Haskell.Syntax.Basic ( HsBang(..) )
 import Language.Haskell.Syntax.Extension
 import Language.Haskell.Syntax.Specificity
 
-import GHC.Types.Name.Reader ( RdrName )
 
 import GHC.Hs.Doc (LHsDoc)
 import GHC.Data.FastString (FastString)
@@ -1367,38 +1365,23 @@ type LFieldOcc pass = XRec pass (FieldOcc pass)
 -- We store both the 'RdrName' the user originally wrote, and after
 -- the renamer we use the extension field to store the selector
 -- function.
+--
+-- There is a wrinkle in that update field occurances are sometimes
+-- ambiguous during the rename stage. See note
+-- [Ambiguous FieldOcc in record updates] to see how we currently
+-- handle this.
 data FieldOcc pass
   = FieldOcc {
         foExt :: XCFieldOcc pass
-      , foLabel :: XRec pass RdrName -- See Note [Located RdrNames] in Language.Haskell.Syntax.Expr
+      , foLabel :: LIdP pass
       }
   | XFieldOcc !(XXFieldOcc pass)
 deriving instance (
-    Eq (XRec pass RdrName)
+    Eq (LIdP pass)
   , Eq (XCFieldOcc pass)
   , Eq (XXFieldOcc pass)
   ) => Eq (FieldOcc pass)
 
--- | Located Ambiguous Field Occurrence
-type LAmbiguousFieldOcc pass = XRec pass (AmbiguousFieldOcc pass)
-
--- | Ambiguous Field Occurrence
---
--- Represents an *occurrence* of a field that is potentially
--- ambiguous after the renamer, with the ambiguity resolved by the
--- typechecker.  We always store the 'RdrName' that the user
--- originally wrote, and store the selector function after the renamer
--- (for unambiguous occurrences) or the typechecker (for ambiguous
--- occurrences).
---
--- See Note [HsRecField and HsRecUpdField] in "GHC.Hs.Pat".
--- See Note [Located RdrNames] in "GHC.Hs.Expr".
-data AmbiguousFieldOcc pass
-  = Unambiguous (XUnambiguous pass) (XRec pass RdrName)
-  | Ambiguous   (XAmbiguous pass)   (XRec pass RdrName)
-  | XAmbiguousFieldOcc !(XXAmbiguousFieldOcc pass)
-
-
 {-
 ************************************************************************
 *                                                                      *
diff --git a/testsuite/tests/parser/should_compile/T14189.stderr b/testsuite/tests/parser/should_compile/T14189.stderr
index 331baa49889..7a61b2d3ad0 100644
--- a/testsuite/tests/parser/should_compile/T14189.stderr
+++ b/testsuite/tests/parser/should_compile/T14189.stderr
@@ -177,7 +177,8 @@
                      (EpaComments
                       []))
                     (FieldOcc
-                     {Name: T14189.f}
+                     (Unqual
+                      {OccName: f})
                      (L
                       (EpAnn
                        (EpaSpan { T14189.hs:6:33 })
@@ -185,8 +186,7 @@
                         [])
                        (EpaComments
                         []))
-                      (Unqual
-                       {OccName: f}))))]
+                      {Name: T14189.f})))]
                   (L
                    (EpAnn
                     (EpaSpan { T14189.hs:6:38-40 })
diff --git a/utils/check-exact/ExactPrint.hs b/utils/check-exact/ExactPrint.hs
index 20901946346..0b42bae688c 100644
--- a/utils/check-exact/ExactPrint.hs
+++ b/utils/check-exact/ExactPrint.hs
@@ -3437,22 +3437,6 @@ instance (ExactPrint body)
 
 -- ---------------------------------------------------------------------
 
-instance (ExactPrint (LocatedA body))
-    => ExactPrint (HsFieldBind (LocatedA (AmbiguousFieldOcc GhcPs)) (LocatedA body)) where
-  getAnnotationEntry _ = NoEntryVal
-  setAnnotationAnchor a _ _ _ = a
-
-  exact (HsFieldBind an f arg isPun) = do
-    debugM $ "HsRecUpdField"
-    f' <- markAnnotated f
-    an0 <- if isPun then return an
-             else markEpAnnL an lidl AnnEqual
-    arg' <- if isPun
-              then return arg
-              else markAnnotated arg
-    return (HsFieldBind an0 f' arg' isPun)
-
--- ---------------------------------------------------------------------
 instance ExactPrint (LHsRecUpdFields GhcPs) where
   getAnnotationEntry = const NoEntryVal
   setAnnotationAnchor a _ _ _ = a
@@ -4523,14 +4507,6 @@ instance ExactPrint (FieldOcc GhcPs) where
 
 -- ---------------------------------------------------------------------
 
-instance ExactPrint (AmbiguousFieldOcc GhcPs) where
-  getAnnotationEntry = const NoEntryVal
-  setAnnotationAnchor a _ _ _ = a
-  exact f@(Unambiguous _ n) = markAnnotated n >> return f
-  exact f@(Ambiguous   _ n) = markAnnotated n >> return f
-
--- ---------------------------------------------------------------------
-
 instance (ExactPrint a) => ExactPrint (HsScaled GhcPs a) where
   getAnnotationEntry = const NoEntryVal
   setAnnotationAnchor a _ _ _ = a
diff --git a/utils/haddock/haddock-api/src/Haddock/Backends/Hoogle.hs b/utils/haddock/haddock-api/src/Haddock/Backends/Hoogle.hs
index a9eb97da186..9fdb57cb02b 100644
--- a/utils/haddock/haddock-api/src/Haddock/Backends/Hoogle.hs
+++ b/utils/haddock/haddock-api/src/Haddock/Backends/Hoogle.hs
@@ -300,7 +300,7 @@ ppCtor sDocContext dat subdocs con@ConDeclH98{con_args = con_args'} =
     f (RecCon (L _ recs)) =
       f (PrefixCon [] $ map (hsLinear . cd_fld_type . unLoc) recs)
         ++ concat
-          [ (concatMap (lookupCon sDocContext subdocs . noLocA . foExt . unLoc) (cd_fld_names r))
+          [ (concatMap (lookupCon sDocContext subdocs . noLocA . unLoc . foLabel . unLoc) (cd_fld_names r))
             ++ [out sDocContext (map (foExt . unLoc) $ cd_fld_names r) `typeSig` [resType, cd_fld_type r]]
           | r <- map unLoc recs
           ]
diff --git a/utils/haddock/haddock-api/src/Haddock/Backends/LaTeX.hs b/utils/haddock/haddock-api/src/Haddock/Backends/LaTeX.hs
index e2262e584f0..431ba46aa61 100644
--- a/utils/haddock/haddock-api/src/Haddock/Backends/LaTeX.hs
+++ b/utils/haddock/haddock-api/src/Haddock/Backends/LaTeX.hs
@@ -1027,7 +1027,7 @@ ppSideBySideConstr subdocs unicode leader (L _ con) =
 ppSideBySideField :: [(DocName, DocForDecl DocName)] -> Bool -> ConDeclField DocNameI -> LaTeX
 ppSideBySideField subdocs unicode (ConDeclField _ names ltype _) =
   decltt
-    ( cat (punctuate comma (map (ppBinder . rdrNameOcc . unLoc . foLabel . unLoc) names))
+    ( cat (punctuate comma (map (ppBinder . rdrNameOcc . foExt . unLoc) names))
         <+> dcolon unicode
         <+> ppLType unicode ltype
     )
@@ -1035,7 +1035,7 @@ ppSideBySideField subdocs unicode (ConDeclField _ names ltype _) =
   where
     -- don't use cd_fld_doc for same reason we don't use con_doc above
     -- Where there is more than one name, they all have the same documentation
-    mbDoc = lookup (foExt $ unLoc name) subdocs >>= fmap _doc . combineDocumentation . fst
+    mbDoc = lookup (unLoc . foLabel . unLoc $ name) subdocs >>= fmap _doc . combineDocumentation . fst
     name =
       case Maybe.listToMaybe names of
         Nothing -> error "No names. An invariant was broken. Please report this to the Haddock project"
diff --git a/utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs b/utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs
index 8de1b082485..802cbb49c06 100644
--- a/utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs
+++ b/utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs
@@ -1536,7 +1536,7 @@ ppSideBySideField subdocs unicode qual (ConDeclField _ names ltype _) =
           comma
           [ ppBinder False (rdrNameOcc field)
           | L _ name <- names
-          , let field = (unLoc . foLabel) name
+          , let field = (foExt) name
           ]
       )
       <+> dcolon unicode
@@ -1547,14 +1547,14 @@ ppSideBySideField subdocs unicode qual (ConDeclField _ names ltype _) =
   where
     -- don't use cd_fld_doc for same reason we don't use con_doc above
     -- Where there is more than one name, they all have the same documentation
-    mbDoc = lookup (foExt $ unLoc declName) subdocs >>= combineDocumentation . fst
+    mbDoc = lookup (unLoc . foLabel $ unLoc declName) subdocs >>= combineDocumentation . fst
     declName = case Maybe.listToMaybe names of
       Nothing -> error "No names. An invariant was broken. Please report this to the Haddock project"
       Just hd -> hd
 
 ppShortField :: Bool -> Unicode -> Qualification -> ConDeclField DocNameI -> Html
 ppShortField summary unicode qual (ConDeclField _ names ltype _) =
-  hsep (punctuate comma (map ((ppBinder summary) . rdrNameOcc . unLoc . foLabel . unLoc) names))
+  hsep (punctuate comma (map ((ppBinder summary) . rdrNameOcc . foExt . unLoc) names))
     <+> dcolon unicode
     <+> ppLType unicode qual HideEmptyContexts ltype
 
diff --git a/utils/haddock/haddock-api/src/Haddock/Convert.hs b/utils/haddock/haddock-api/src/Haddock/Convert.hs
index cc9aea2fd76..4034d49af45 100644
--- a/utils/haddock/haddock-api/src/Haddock/Convert.hs
+++ b/utils/haddock/haddock-api/src/Haddock/Convert.hs
@@ -506,7 +506,7 @@ synifyDataCon use_gadt_syntax dc =
       noLocA $
         ConDeclField
           noAnn
-          [noLocA $ FieldOcc (flSelector fl) (noLocA $ mkVarUnqual $ field_label $ flLabel fl)]
+          [noLocA $ FieldOcc (mkVarUnqual $ field_label $ flLabel fl) (noLocA  (flSelector fl))]
           synTy
           Nothing
 
diff --git a/utils/haddock/haddock-api/src/Haddock/GhcUtils.hs b/utils/haddock/haddock-api/src/Haddock/GhcUtils.hs
index 7644a1fa237..0d92c3a0f3c 100644
--- a/utils/haddock/haddock-api/src/Haddock/GhcUtils.hs
+++ b/utils/haddock/haddock-api/src/Haddock/GhcUtils.hs
@@ -360,7 +360,7 @@ restrictCons names decls = [L p d | L p (Just d) <- fmap keep <$> decls]
 
         field_avail :: LConDeclField GhcRn -> Bool
         field_avail (L _ (ConDeclField _ fs _ _)) =
-          all (\f -> foExt (unLoc f) `elem` names) fs
+          all (\f -> (unLoc . foLabel . unLoc $ f) `elem` names) fs
 
         field_types flds = [hsUnrestricted t | L _ (ConDeclField _ _ t _) <- flds]
     keep _ = Nothing
@@ -553,7 +553,7 @@ instance Parent (ConDecl GhcRn) where
   children con =
     case getRecConArgs_maybe con of
       Nothing -> []
-      Just flds -> map (foExt . unLoc) $ concatMap (cd_fld_names . unLoc) (unLoc flds)
+      Just flds -> map (unLoc . foLabel . unLoc) $ concatMap (cd_fld_names . unLoc) (unLoc flds)
 
 instance Parent (TyClDecl GhcRn) where
   children d
diff --git a/utils/haddock/haddock-api/src/Haddock/Interface/Create.hs b/utils/haddock/haddock-api/src/Haddock/Interface/Create.hs
index bf384e1b44c..f17f0ad58d8 100644
--- a/utils/haddock/haddock-api/src/Haddock/Interface/Create.hs
+++ b/utils/haddock/haddock-api/src/Haddock/Interface/Create.hs
@@ -935,7 +935,7 @@ extractDecl prr dflags sDocContext name decl
                     Just rec <- toList $ getRecConArgs_maybe . unLoc <$> dd_cons (feqn_rhs d)
                     , ConDeclField{cd_fld_names = ns} <- map unLoc (unLoc rec)
                     , L _ n <- ns
-                    , foExt n == name
+                    , unLoc (foLabel n) == name
                     ]
                in case matches of
                     [d0] -> extractDecl prr dflags sDocContext name (noLocA . InstD noExtField $ DataFamInstD noExtField d0)
@@ -1004,7 +1004,7 @@ extractRecSel nm t tvs (L _ con : rest) =
   where
     matching_fields :: [LConDeclField GhcRn] -> [(SrcSpan, LConDeclField GhcRn)]
     matching_fields flds =
-      [ (locA l, f) | f@(L _ (ConDeclField _ ns _ _)) <- flds, L l n <- ns, foExt n == nm
+      [ (locA l, f) | f@(L _ (ConDeclField _ ns _ _)) <- flds, L l n <- ns, unLoc (foLabel n) == nm
       ]
     data_ty
       -- ResTyGADT _ ty <- con_res con = ty
diff --git a/utils/haddock/haddock-api/src/Haddock/Interface/Rename.hs b/utils/haddock/haddock-api/src/Haddock/Interface/Rename.hs
index 732de63e980..da50807b235 100644
--- a/utils/haddock/haddock-api/src/Haddock/Interface/Rename.hs
+++ b/utils/haddock/haddock-api/src/Haddock/Interface/Rename.hs
@@ -748,9 +748,9 @@ renameConDeclFieldField (L l (ConDeclField _ names t doc)) = do
   return $ L (locA l) (ConDeclField noExtField names' t' doc')
 
 renameLFieldOcc :: LFieldOcc GhcRn -> RnM (LFieldOcc DocNameI)
-renameLFieldOcc (L l (FieldOcc sel lbl)) = do
+renameLFieldOcc (L l (FieldOcc rdr (L n sel))) = do
   sel' <- renameName sel
-  return $ L l (FieldOcc sel' lbl)
+  return $ L l (FieldOcc rdr (L n sel'))
 
 renameSig :: Sig GhcRn -> RnM (Sig DocNameI)
 renameSig sig = case sig of
diff --git a/utils/haddock/haddock-api/src/Haddock/Types.hs b/utils/haddock/haddock-api/src/Haddock/Types.hs
index 73934fc0939..f71a3f04aee 100644
--- a/utils/haddock/haddock-api/src/Haddock/Types.hs
+++ b/utils/haddock/haddock-api/src/Haddock/Types.hs
@@ -886,8 +886,8 @@ type instance XBndrKind DocNameI = NoExtField
 type instance XBndrNoKind DocNameI = NoExtField
 type instance XXBndrKind DocNameI = DataConCantHappen
 
-type instance XCFieldOcc DocNameI = DocName
-type instance XXFieldOcc DocNameI = NoExtField
+type instance XCFieldOcc DocNameI = RdrName
+type instance XXFieldOcc DocNameI = DataConCantHappen
 
 type instance XFixitySig DocNameI = NoExtField
 type instance XFixSig DocNameI = NoExtField
-- 
GitLab