Apoorv Ingle pushed to branch wip/ani/T27156 at Glasgow Haskell Compiler / GHC

Commits:

7 changed files:

Changes:

  • compiler/GHC/Hs/Expr.hs
    ... ... @@ -340,13 +340,13 @@ type instance XLHsRecUpdLabels GhcTc = DataConCantHappen
    340 340
     type instance XLHsOLRecUpdLabels p = NoExtField
    
    341 341
     
    
    342 342
     type instance XGetField     GhcPs = NoExtField
    
    343
    -type instance XGetField     GhcRn = NoExtField
    
    343
    +type instance XGetField     GhcRn = Name
    
    344 344
     type instance XGetField     GhcTc = DataConCantHappen
    
    345 345
     -- HsGetField is eliminated by the renamer. See [Handling overloaded
    
    346 346
     -- and rebindable constructs].
    
    347 347
     
    
    348 348
     type instance XProjection     GhcPs = AnnProjection
    
    349
    -type instance XProjection     GhcRn = NoExtField
    
    349
    +type instance XProjection     GhcRn = (Name, Name)
    
    350 350
     type instance XProjection     GhcTc = DataConCantHappen
    
    351 351
     -- HsProjection is eliminated by the renamer. See [Handling overloaded
    
    352 352
     -- and rebindable constructs].
    

  • compiler/GHC/Rename/Expr.hs
    ... ... @@ -72,7 +72,7 @@ import qualified GHC.LanguageExtensions as LangExt
    72 72
     import Control.Monad
    
    73 73
     import qualified Data.Foldable as Partial (maximum)
    
    74 74
     import Data.List (unzip4)
    
    75
    -import Data.List.NonEmpty ( NonEmpty(..), head, init, last, nonEmpty, scanl, tail )
    
    75
    +import Data.List.NonEmpty ( NonEmpty(..), head, nonEmpty, scanl, tail )
    
    76 76
     import Control.Arrow (first)
    
    77 77
     import Data.Ord
    
    78 78
     import Data.Array
    
    ... ... @@ -419,19 +419,13 @@ rnExpr (HsGetField _ e f)
    419 419
      = do { (getField, fv_getField) <- lookupSyntaxName getFieldName
    
    420 420
           ; (e, fv_e) <- rnLExpr e
    
    421 421
           ; let f' = rnDotFieldOcc <$> f
    
    422
    -      ; return ( mkExpandedExpr
    
    423
    -                   (HsGetField noExtField e f')
    
    424
    -                   (mkGetField getField e (fmap (unLoc . dfoLabel) f'))
    
    425
    -               , fv_e `plusFN` fv_getField ) }
    
    422
    +      ; return (HsGetField getField e f', fv_e `plusFN` fv_getField) }
    
    426 423
     
    
    427 424
     rnExpr (HsProjection _ fs)
    
    428 425
       = do { (getField, fv_getField) <- lookupSyntaxName getFieldName
    
    429 426
            ; circ <- lookupOccRn WL_TermVariable compose_RDR
    
    430 427
            ; let fs' = NE.map rnDotFieldOcc fs
    
    431
    -       ; return ( mkExpandedExpr
    
    432
    -                    (HsProjection noExtField fs')
    
    433
    -                    (mkProjection getField circ $ NE.map (unLoc . dfoLabel) fs')
    
    434
    -                , unitFN circ `plusFN` fv_getField) }
    
    428
    +       ; return (HsProjection (getField , circ) fs', unitFN circ `plusFN` fv_getField) }
    
    435 429
     
    
    436 430
     ------------------------------------------
    
    437 431
     -- Template Haskell extensions
    
    ... ... @@ -717,14 +711,12 @@ rnSection :: HsExpr GhcPs -> RnM (HsExpr GhcRn, FreeNames)
    717 711
     -- Also see Note [Handling overloaded and rebindable constructs]
    
    718 712
     
    
    719 713
     rnSection section@(SectionR x op expr)
    
    720
    -  -- See Note [Left and right sections]
    
    721 714
       = do  { (op', fvs_op)     <- rnLExpr op
    
    722 715
             ; (expr', fvs_expr) <- rnLExpr expr
    
    723 716
             ; checkSectionPrec InfixR section op' expr'
    
    724 717
             ; return $ (SectionR x op' expr' , fvs_op `plusFN`  fvs_expr) }
    
    725 718
     
    
    726 719
     rnSection section@(SectionL x expr op)
    
    727
    -  -- See Note [Left and right sections]
    
    728 720
       = do  { (expr', fvs_expr) <- rnLExpr expr
    
    729 721
             ; (op', fvs_op)     <- rnLExpr op
    
    730 722
             ; checkSectionPrec InfixL section op' expr'
    
    ... ... @@ -732,129 +724,7 @@ rnSection section@(SectionL x expr op)
    732 724
     
    
    733 725
     rnSection other = pprPanic "rnSection" (ppr other)
    
    734 726
     
    
    735
    -{- Note [Left and right sections]
    
    736
    -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    737
    -Dealing with left sections (x *) and right sections (* x) is
    
    738
    -surprisingly fiddly.  We expand like this
    
    739
    -     (`op` e) ==> rightSection op e
    
    740
    -     (e `op`) ==> leftSection  (op e)
    
    741
    -
    
    742
    -Using an auxiliary function in this way avoids the awkwardness of
    
    743
    -generating a lambda, esp if `e` is a redex, so we *don't* want
    
    744
    -to generate `(\x -> op x e)`. See Historical
    
    745
    -Note [Desugaring operator sections]
    
    746
    -
    
    747
    -Here are their definitions:
    
    748
    -   leftSection :: forall r1 r2 n (a::TYPE r1) (b::TYPE r2).
    
    749
    -                  (a %n-> b) -> a %n-> b
    
    750
    -   leftSection f x = f x
    
    751
    -
    
    752
    -   rightSection :: forall r1 r2 r3 n1 n2 (a::TYPE r1) (b::TYPE r2) (c::TYPE r3).
    
    753
    -                   (a %n1 -> b %n2-> c) -> b %n2-> a %n1-> c
    
    754
    -   rightSection f y x = f x y
    
    755
    -
    
    756
    -Note the wrinkles:
    
    757
    -
    
    758
    -* We do /not/ use lookupSyntaxName, which would make left and right
    
    759
    -  section fall under RebindableSyntax.  Reason: it would be a user-
    
    760
    -  facing change, and there are some tricky design choices (#19354).
    
    761
    -  Plus, infix operator applications would be trickier to make
    
    762
    -  rebindable, so it'd be inconsistent to do so for sections.
    
    763
    -
    
    764
    -  TL;DR: we still use the renamer-expansion mechanism for operator
    
    765
    -  sections, but only to eliminate special-purpose code paths in the
    
    766
    -  renamer and desugarer.
    
    767
    -
    
    768
    -* leftSection and rightSection must be representation-polymorphic, to allow
    
    769
    -  (+# 4#) and (4# +#) to work. See
    
    770
    -  Note [Wired-in Ids for rebindable syntax] in GHC.Types.Id.Make.
    
    771
    -
    
    772
    -* leftSection and rightSection must be multiplicity-polymorphic.
    
    773
    -  (Test linear/should_compile/OldList showed this up.)
    
    774
    -
    
    775
    -* Because they are representation-polymorphic, we have to define them
    
    776
    -  as wired-in Ids, with compulsory inlining.  See
    
    777
    -  GHC.Types.Id.Make.leftSectionId, rightSectionId.
    
    778
    -
    
    779
    -* leftSection is just ($) really; but unlike ($) it is
    
    780
    -  representation-polymorphic in the result type, so we can write
    
    781
    -  `(x +#)`, say.
    
    782
    -
    
    783
    -* The type of leftSection must have an arrow in its first argument,
    
    784
    -  because (x `ord`) should be rejected, because ord does not take two
    
    785
    -  arguments
    
    786
    -
    
    787
    -* It's important that we define leftSection in an eta-expanded way,
    
    788
    -  (i.e. not leftSection f = f), so that
    
    789
    -      (True `undefined`) `seq` ()
    
    790
    -      = (leftSection (undefined True) `seq` ())
    
    791
    -  evaluates to () and not undefined
    
    792
    -
    
    793
    -* If PostfixOperators is ON, then we expand a left section like this:
    
    794
    -      (e `op`)  ==>   op e
    
    795
    -  with no auxiliary function at all.  Simple!
    
    796
    -
    
    797
    -* leftSection and rightSection switch on ImpredicativeTypes locally,
    
    798
    -  during Quick Look; see GHC.Tc.Gen.App.wantQuickLook. Consider
    
    799
    -  test DeepSubsumption08:
    
    800
    -     type Setter st t a b = forall f. Identical f => blah
    
    801
    -     (.~) :: Setter s t a b -> b -> s -> t
    
    802
    -     clear :: Setter a a' b (Maybe b') -> a -> a'
    
    803
    -     clear = (.~ Nothing)
    
    804
    -   The expansion look like (rightSection (.~) Nothing).  So we must
    
    805
    -   instantiate `rightSection` first type argument to a polytype!
    
    806
    -   Hence the special magic in App.wantQuickLook.
    
    807
    -
    
    808
    -Historical Note [Desugaring operator sections]
    
    809
    -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    810
    -This Note explains some historical trickiness in desugaring left and
    
    811
    -right sections.  That trickiness has completely disappeared now that
    
    812
    -we desugar to calls to 'leftSection` and `rightSection`, but I'm
    
    813
    -leaving it here to remind us how nice the new story is.
    
    814
    -
    
    815
    -Desugaring left sections with -XPostfixOperators is straightforward: convert
    
    816
    -(expr `op`) to (op expr).
    
    817
    -
    
    818
    -Without -XPostfixOperators it's a bit more tricky. At first it looks as if we
    
    819
    -can convert
    
    820
    -
    
    821
    -    (expr `op`)
    
    822
    -
    
    823
    -naively to
    
    824
    -
    
    825
    -    \x -> op expr x
    
    826
    -
    
    827
    -But no!  expr might be a redex, and we can lose laziness badly this
    
    828
    -way.  Consider
    
    829
    -
    
    830
    -    map (expr `op`) xs
    
    831
    -
    
    832
    -for example. If expr were a redex then eta-expanding naively would
    
    833
    -result in multiple evaluations where the user might only have expected one.
    
    834
    -
    
    835
    -So we convert instead to
    
    836
    -
    
    837
    -    let y = expr in \x -> op y x
    
    838
    -
    
    839
    -Also, note that we must do this for both right and (perhaps surprisingly) left
    
    840
    -sections. Why are left sections necessary? Consider the program (found in #18151),
    
    841
    -
    
    842
    -    seq (True `undefined`) ()
    
    843
    -
    
    844
    -according to the Haskell Report this should reduce to () (as it specifies
    
    845
    -desugaring via eta expansion). However, if we fail to eta expand we will rather
    
    846
    -bottom. Consequently, we must eta expand even in the case of a left section.
    
    847
    -
    
    848
    -If `expr` is actually just a variable, say, then the simplifier
    
    849
    -will inline `y`, eliminating the redundant `let`.
    
    850
    -
    
    851
    -Note that this works even in the case that `expr` is unlifted. In this case
    
    852
    -bindNonRec will automatically do the right thing, giving us:
    
    853
    -
    
    854
    -    case expr of y -> (\x -> op y x)
    
    855
    -
    
    856
    -See #18151.
    
    857
    -
    
    727
    +{-
    
    858 728
     Note [Reporting unbound names]
    
    859 729
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    860 730
     Faced with an out-of-scope `RdrName` there are two courses of action
    
    ... ... @@ -2841,64 +2711,6 @@ rnHsIf p b1 b2
    2841 2711
                               fvs   = plusFNs [fvs_if, unitFN ite_name]
    
    2842 2712
                         ; return (mkExpandedExpr rn_if ds_if, fvs) } }
    
    2843 2713
     
    
    2844
    ------------------------------------------
    
    2845
    --- Bits and pieces for RecordDotSyntax.
    
    2846
    ---
    
    2847
    --- See Note [Overview of record dot syntax] in GHC.Hs.Expr.
    
    2848
    -
    
    2849
    --- mkGetField arg field calculates a get_field @field arg expression.
    
    2850
    --- e.g. z.x = mkGetField z x = get_field @x z
    
    2851
    -mkGetField :: Name -> LHsExpr GhcRn -> LocatedAn NoEpAnns FieldLabelString -> HsExpr GhcRn
    
    2852
    -mkGetField get_field arg field = unLoc (head $ mkGet get_field (arg :| []) field)
    
    2853
    -
    
    2854
    --- mkSetField a field b calculates a set_field @field expression.
    
    2855
    --- e.g mkSetSetField a field b = set_field @"field" a b (read as "set field 'field' to a on b").
    
    2856
    --- NB: the order of aruments is specified by GHC Proposal 583: HasField redesign.
    
    2857
    -mkSetField :: Name -> LHsExpr GhcRn -> LocatedAn NoEpAnns FieldLabelString -> LHsExpr GhcRn -> HsExpr GhcRn
    
    2858
    -mkSetField set_field a (L _ (FieldLabelString field)) b =
    
    2859
    -  genHsApp (genHsApp (genHsVar set_field `genAppType` genHsTyLit field) b) a
    
    2860
    -
    
    2861
    -mkGet :: Name -> NonEmpty (LHsExpr GhcRn) -> LocatedAn NoEpAnns FieldLabelString -> NonEmpty (LHsExpr GhcRn)
    
    2862
    -mkGet get_field l@(r :| _) (L _ (FieldLabelString field)) =
    
    2863
    -  wrapGenSpan (genHsApp (genHsVar get_field `genAppType` genHsTyLit field) r) NE.<| l
    
    2864
    -
    
    2865
    -mkSet :: Name -> LHsExpr GhcRn -> (LocatedAn NoEpAnns FieldLabelString, LHsExpr GhcRn) -> LHsExpr GhcRn
    
    2866
    -mkSet set_field acc (field, g) = wrapGenSpan (mkSetField set_field g field acc)
    
    2867
    -
    
    2868
    --- mkProjection fields calculates a projection.
    
    2869
    --- e.g. .x = mkProjection [x] = getField @"x"
    
    2870
    ---      .x.y = mkProjection [.x, .y] = (.y) . (.x) = getField @"y" . getField @"x"
    
    2871
    -mkProjection :: Name -> Name -> NonEmpty FieldLabelString -> HsExpr GhcRn
    
    2872
    -mkProjection getFieldName circName (field :| fields) = foldl' f (proj field) fields
    
    2873
    -  where
    
    2874
    -    f :: HsExpr GhcRn -> FieldLabelString -> HsExpr GhcRn
    
    2875
    -    f acc field = genHsApps circName $ map wrapGenSpan [proj field, acc]
    
    2876
    -
    
    2877
    -    proj :: FieldLabelString -> HsExpr GhcRn
    
    2878
    -    proj (FieldLabelString f) = genHsVar getFieldName `genAppType` genHsTyLit f
    
    2879
    -
    
    2880
    --- mkProjUpdateSetField calculates functions representing dot notation record updates.
    
    2881
    --- e.g. Suppose an update like foo.bar = 1.
    
    2882
    ---      We calculate the function \a -> setField @"foo" a (setField @"bar" (getField @"foo" a) 1).
    
    2883
    -mkProjUpdateSetField :: Name -> Name -> LHsRecProj GhcRn (LHsExpr GhcRn) -> (LHsExpr GhcRn -> LHsExpr GhcRn)
    
    2884
    -mkProjUpdateSetField get_field set_field (L _ (HsFieldBind { hfbLHS = (L _ (FieldLabelStrings flds')), hfbRHS = arg } ))
    
    2885
    -  = let {
    
    2886
    -      ; flds = NE.map (fmap (unLoc . dfoLabel)) flds'
    
    2887
    -      ; final = last flds  -- quux
    
    2888
    -      ; fields = init flds   -- [foo, bar, baz]
    
    2889
    -      ; getters = \a -> foldl' (mkGet get_field) (a :| []) fields  -- Ordered from deep to shallow.
    
    2890
    -          -- [getField@"baz"(getField@"bar"(getField@"foo" a), getField@"bar"(getField@"foo" a), getField@"foo" a, a]
    
    2891
    -      ; zips = \a -> (final, head (getters a)) : zip (reverse fields) (tail (getters a)) -- Ordered from deep to shallow.
    
    2892
    -          -- [("quux", getField@"baz"(getField@"bar"(getField@"foo" a)), ("baz", getField@"bar"(getField@"foo" a)), ("bar", getField@"foo" a), ("foo", a)]
    
    2893
    -      }
    
    2894
    -    in (\a -> foldl' (mkSet set_field) arg (zips a))
    
    2895
    -          -- setField@"foo" (a) (setField@"bar" (getField @"foo" (a))(setField@"baz" (getField @"bar" (getField @"foo" (a)))(setField@"quux" (getField @"baz" (getField @"bar" (getField @"foo" (a))))(quux))))
    
    2896
    -
    
    2897
    -mkRecordDotUpd :: Name -> Name -> LHsExpr GhcRn -> [LHsRecUpdProj GhcRn] -> HsExpr GhcRn
    
    2898
    -mkRecordDotUpd get_field set_field exp updates = foldl' fieldUpdate (unLoc exp) updates
    
    2899
    -  where
    
    2900
    -    fieldUpdate :: HsExpr GhcRn -> LHsRecUpdProj GhcRn -> HsExpr GhcRn
    
    2901
    -    fieldUpdate acc lpu =  unLoc $ (mkProjUpdateSetField get_field set_field lpu) (wrapGenSpan acc)
    
    2902 2714
     
    
    2903 2715
     rnHsUpdProjs :: [LHsRecUpdProj GhcPs] -> RnM ([LHsRecUpdProj GhcRn], FreeNames)
    
    2904 2716
     rnHsUpdProjs us = do
    

  • compiler/GHC/Rename/Utils.hs
    ... ... @@ -24,6 +24,8 @@ module GHC.Rename.Utils (
    24 24
             genSimpleFunBind, genFunBind,
    
    25 25
             genHsLamDoExp, genHsCaseAltDoExp, genSimpleMatch, genHsLet,
    
    26 26
     
    
    27
    +        mkGetField, mkSetField, mkProjection, mkRecordDotUpd,
    
    28
    +
    
    27 29
             mkExpandedRn, mkExpandedExpr, mkExpandedStmt, mkExpandedLExpr, mkExpandedTc, mkExpandedExprTc,
    
    28 30
     
    
    29 31
             mkRnSyntaxExpr,
    
    ... ... @@ -41,7 +43,7 @@ module GHC.Rename.Utils (
    41 43
     where
    
    42 44
     
    
    43 45
     
    
    44
    -import GHC.Prelude
    
    46
    +import GHC.Prelude hiding (init, last, scanl, tail)
    
    45 47
     
    
    46 48
     import GHC.Core.Type
    
    47 49
     import GHC.Hs
    
    ... ... @@ -71,6 +73,7 @@ import GHC.Iface.Load
    71 73
     import qualified GHC.LanguageExtensions as LangExt
    
    72 74
     
    
    73 75
     import qualified Data.List.NonEmpty as NE
    
    76
    +import Data.List.NonEmpty ( NonEmpty(..), init, last, tail )
    
    74 77
     import Data.Foldable (for_)
    
    75 78
     import Data.Maybe
    
    76 79
     
    
    ... ... @@ -867,3 +870,63 @@ mkExpandedTc
    867 870
       -> LHsExpr GhcTc           -- ^ expanded typechecked expression
    
    868 871
       -> HsExpr GhcTc           -- ^ suitably wrapped 'XXExprGhcTc'
    
    869 872
     mkExpandedTc o e = XExpr (ExpandedThingTc (HSE o e))
    
    873
    +
    
    874
    +
    
    875
    +-----------------------------------------
    
    876
    +-- Bits and pieces for RecordDotSyntax.
    
    877
    +--
    
    878
    +-- See Note [Overview of record dot syntax] in GHC.Hs.Expr.
    
    879
    +
    
    880
    +-- mkGetField arg field calculates a get_field @field arg expression.
    
    881
    +-- e.g. z.x = mkGetField z x = get_field @x z
    
    882
    +mkGetField :: Name -> LHsExpr GhcRn -> LocatedAn NoEpAnns FieldLabelString -> HsExpr GhcRn
    
    883
    +mkGetField get_field arg field = unLoc (NE.head $ mkGet get_field (arg :| []) field)
    
    884
    +
    
    885
    +-- mkSetField a field b calculates a set_field @field expression.
    
    886
    +-- e.g mkSetSetField a field b = set_field @"field" a b (read as "set field 'field' to a on b").
    
    887
    +-- NB: the order of aruments is specified by GHC Proposal 583: HasField redesign.
    
    888
    +mkSetField :: Name -> LHsExpr GhcRn -> LocatedAn NoEpAnns FieldLabelString -> LHsExpr GhcRn -> HsExpr GhcRn
    
    889
    +mkSetField set_field a (L _ (FieldLabelString field)) b =
    
    890
    +  genHsApp (genHsApp (genHsVar set_field `genAppType` genHsTyLit field) b) a
    
    891
    +
    
    892
    +mkGet :: Name -> NonEmpty (LHsExpr GhcRn) -> LocatedAn NoEpAnns FieldLabelString -> NonEmpty (LHsExpr GhcRn)
    
    893
    +mkGet get_field l@(r :| _) (L _ (FieldLabelString field)) =
    
    894
    +  wrapGenSpan (genHsApp (genHsVar get_field `genAppType` genHsTyLit field) r) NE.<| l
    
    895
    +
    
    896
    +mkSet :: Name -> LHsExpr GhcRn -> (LocatedAn NoEpAnns FieldLabelString, LHsExpr GhcRn) -> LHsExpr GhcRn
    
    897
    +mkSet set_field acc (field, g) = wrapGenSpan (mkSetField set_field g field acc)
    
    898
    +
    
    899
    +-- mkProjection fields calculates a projection.
    
    900
    +-- e.g. .x = mkProjection [x] = getField @"x"
    
    901
    +--      .x.y = mkProjection [.x, .y] = (.y) . (.x) = getField @"y" . getField @"x"
    
    902
    +mkProjection :: Name -> Name -> NonEmpty FieldLabelString -> HsExpr GhcRn
    
    903
    +mkProjection getFieldName circName (field :| fields) = foldl' f (proj field) fields
    
    904
    +  where
    
    905
    +    f :: HsExpr GhcRn -> FieldLabelString -> HsExpr GhcRn
    
    906
    +    f acc field = genHsApps circName $ map wrapGenSpan [proj field, acc]
    
    907
    +
    
    908
    +    proj :: FieldLabelString -> HsExpr GhcRn
    
    909
    +    proj (FieldLabelString f) = genHsVar getFieldName `genAppType` genHsTyLit f
    
    910
    +
    
    911
    +-- mkProjUpdateSetField calculates functions representing dot notation record updates.
    
    912
    +-- e.g. Suppose an update like foo.bar = 1.
    
    913
    +--      We calculate the function \a -> setField @"foo" a (setField @"bar" (getField @"foo" a) 1).
    
    914
    +mkProjUpdateSetField :: Name -> Name -> LHsRecProj GhcRn (LHsExpr GhcRn) -> (LHsExpr GhcRn -> LHsExpr GhcRn)
    
    915
    +mkProjUpdateSetField get_field set_field (L _ (HsFieldBind { hfbLHS = (L _ (FieldLabelStrings flds')), hfbRHS = arg } ))
    
    916
    +  = let {
    
    917
    +      ; flds = NE.map (fmap (unLoc . dfoLabel)) flds'
    
    918
    +      ; final = last flds  -- quux
    
    919
    +      ; fields = init flds   -- [foo, bar, baz]
    
    920
    +      ; getters = \a -> foldl' (mkGet get_field) (a :| []) fields  -- Ordered from deep to shallow.
    
    921
    +          -- [getField@"baz"(getField@"bar"(getField@"foo" a), getField@"bar"(getField@"foo" a), getField@"foo" a, a]
    
    922
    +      ; zips = \a -> (final, NE.head (getters a)) : zip (reverse fields) (tail (getters a)) -- Ordered from deep to shallow.
    
    923
    +          -- [("quux", getField@"baz"(getField@"bar"(getField@"foo" a)), ("baz", getField@"bar"(getField@"foo" a)), ("bar", getField@"foo" a), ("foo", a)]
    
    924
    +      }
    
    925
    +    in (\a -> foldl' (mkSet set_field) arg (zips a))
    
    926
    +          -- setField@"foo" (a) (setField@"bar" (getField @"foo" (a))(setField@"baz" (getField @"bar" (getField @"foo" (a)))(setField@"quux" (getField @"baz" (getField @"bar" (getField @"foo" (a))))(quux))))
    
    927
    +
    
    928
    +mkRecordDotUpd :: Name -> Name -> LHsExpr GhcRn -> [LHsRecUpdProj GhcRn] -> HsExpr GhcRn
    
    929
    +mkRecordDotUpd get_field set_field exp updates = foldl' fieldUpdate (unLoc exp) updates
    
    930
    +  where
    
    931
    +    fieldUpdate :: HsExpr GhcRn -> LHsRecUpdProj GhcRn -> HsExpr GhcRn
    
    932
    +    fieldUpdate acc lpu =  unLoc $ (mkProjUpdateSetField get_field set_field lpu) (wrapGenSpan acc)

  • compiler/GHC/Tc/Gen/Expand.hs
    ... ... @@ -17,8 +17,10 @@ import GHC.Tc.Utils.Monad
    17 17
     import GHC.Tc.Types.ErrCtxt
    
    18 18
     
    
    19 19
     import GHC.Types.Id.Make
    
    20
    +import GHC.Types.SrcLoc
    
    20 21
     
    
    21 22
     import GHC.Rename.Utils
    
    23
    +import qualified Data.List.NonEmpty as NE (map)
    
    22 24
     
    
    23 25
     import qualified GHC.LanguageExtensions as LangExt
    
    24 26
     
    
    ... ... @@ -105,7 +107,8 @@ Wrinkle (TBE1)
    105 107
     
    
    106 108
     -}
    
    107 109
     
    
    108
    ----------------
    
    110
    +------------------------------------------
    
    111
    +-- Operator Applications
    
    109 112
     tcExpand :: HsExpr GhcRn -> TcM (Maybe (HsExpansion GhcRn))
    
    110 113
     tcExpand e@(OpApp _ arg1 op arg2)
    
    111 114
       = return $ Just $
    
    ... ... @@ -114,14 +117,18 @@ tcExpand e@(OpApp _ arg1 op arg2)
    114 117
       where
    
    115 118
         ap f a = wrapGenSpan (HsApp noExtField f a)
    
    116 119
     
    
    120
    +------------------------------------------
    
    121
    +-- Left and Right Sections
    
    122
    +
    
    117 123
     tcExpand e@(SectionR _ op expr)
    
    124
    +  -- See Note [Left and right sections]
    
    118 125
       = return $ Just $
    
    119 126
         HSE { hse_ctxt = ExprCtxt e
    
    120 127
             , hse_exp  = wrapGenSpan $ genHsApps rightSectionName [op, expr] }
    
    121 128
     
    
    122 129
     tcExpand e@(SectionL _ expr op)
    
    130
    +  -- Note [Left and right sections]
    
    123 131
       = do { postfix_ops <- xoptM LangExt.PostfixOperators
    
    124
    -                        -- Note [Left and right sections]
    
    125 132
             ; let ds_section
    
    126 133
                     | postfix_ops = HsApp noExtField op expr
    
    127 134
                     | otherwise   = genHsApps leftSectionName
    
    ... ... @@ -130,10 +137,26 @@ tcExpand e@(SectionL _ expr op)
    130 137
               HSE { hse_ctxt = ExprCtxt e
    
    131 138
                   , hse_exp = wrapGenSpan ds_section } }
    
    132 139
     
    
    140
    +------------------------------------------
    
    141
    +-- Record dot syntax
    
    142
    +
    
    143
    +tcExpand e@(HsGetField getFieldName expr f)
    
    144
    + = return $ Just $
    
    145
    +   HSE { hse_ctxt = ExprCtxt e
    
    146
    +       , hse_exp = wrapGenSpan $ (mkGetField getFieldName expr (fmap (unLoc . dfoLabel) f)) }
    
    147
    +
    
    148
    +tcExpand e@(HsProjection (getFieldName, circName) fs)
    
    149
    + =  return$ Just $
    
    150
    +    HSE { hse_ctxt = ExprCtxt e
    
    151
    +        , hse_exp = wrapGenSpan $ (mkProjection getFieldName circName $ NE.map (unLoc . dfoLabel) fs) }
    
    133 152
     
    
    153
    +---------
    
    134 154
     tcExpand (XExpr (ExpandedThingRn hse))
    
    135 155
       = return (Just hse)
    
    136 156
     
    
    157
    +------------------------------------------
    
    158
    +-- Template Haskell Splices
    
    159
    +
    
    137 160
     tcExpand e@(HsUntypedSplice splice_res _)
    
    138 161
     -- See Note [Looking through Template Haskell splices in splitHsApps]
    
    139 162
       = do { fun <- getUntypedSpliceBody splice_res
    
    ... ... @@ -142,3 +165,132 @@ tcExpand e@(HsUntypedSplice splice_res _)
    142 165
                  , hse_exp  = wrapGenSpan fun } }
    
    143 166
     
    
    144 167
     tcExpand _ = return Nothing
    
    168
    +
    
    169
    +
    
    170
    +
    
    171
    +
    
    172
    +
    
    173
    +
    
    174
    +{- Note [Left and right sections]
    
    175
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    176
    +Dealing with left sections (x *) and right sections (* x) is
    
    177
    +surprisingly fiddly.  We expand like this
    
    178
    +     (`op` e) ==> rightSection op e
    
    179
    +     (e `op`) ==> leftSection  (op e)
    
    180
    +
    
    181
    +Using an auxiliary function in this way avoids the awkwardness of
    
    182
    +generating a lambda, esp if `e` is a redex, so we *don't* want
    
    183
    +to generate `(\x -> op x e)`. See Historical
    
    184
    +Note [Desugaring operator sections]
    
    185
    +
    
    186
    +Here are their definitions:
    
    187
    +   leftSection :: forall r1 r2 n (a::TYPE r1) (b::TYPE r2).
    
    188
    +                  (a %n-> b) -> a %n-> b
    
    189
    +   leftSection f x = f x
    
    190
    +
    
    191
    +   rightSection :: forall r1 r2 r3 n1 n2 (a::TYPE r1) (b::TYPE r2) (c::TYPE r3).
    
    192
    +                   (a %n1 -> b %n2-> c) -> b %n2-> a %n1-> c
    
    193
    +   rightSection f y x = f x y
    
    194
    +
    
    195
    +Note the wrinkles:
    
    196
    +
    
    197
    +* We do /not/ use lookupSyntaxName, which would make left and right
    
    198
    +  section fall under RebindableSyntax.  Reason: it would be a user-
    
    199
    +  facing change, and there are some tricky design choices (#19354).
    
    200
    +  Plus, infix operator applications would be trickier to make
    
    201
    +  rebindable, so it'd be inconsistent to do so for sections.
    
    202
    +
    
    203
    +  TL;DR: we still use the renamer-expansion mechanism for operator
    
    204
    +  sections, but only to eliminate special-purpose code paths in the
    
    205
    +  renamer and desugarer.
    
    206
    +
    
    207
    +* leftSection and rightSection must be representation-polymorphic, to allow
    
    208
    +  (+# 4#) and (4# +#) to work. See
    
    209
    +  Note [Wired-in Ids for rebindable syntax] in GHC.Types.Id.Make.
    
    210
    +
    
    211
    +* leftSection and rightSection must be multiplicity-polymorphic.
    
    212
    +  (Test linear/should_compile/OldList showed this up.)
    
    213
    +
    
    214
    +* Because they are representation-polymorphic, we have to define them
    
    215
    +  as wired-in Ids, with compulsory inlining.  See
    
    216
    +  GHC.Types.Id.Make.leftSectionId, rightSectionId.
    
    217
    +
    
    218
    +* leftSection is just ($) really; but unlike ($) it is
    
    219
    +  representation-polymorphic in the result type, so we can write
    
    220
    +  `(x +#)`, say.
    
    221
    +
    
    222
    +* The type of leftSection must have an arrow in its first argument,
    
    223
    +  because (x `ord`) should be rejected, because ord does not take two
    
    224
    +  arguments
    
    225
    +
    
    226
    +* It's important that we define leftSection in an eta-expanded way,
    
    227
    +  (i.e. not leftSection f = f), so that
    
    228
    +      (True `undefined`) `seq` ()
    
    229
    +      = (leftSection (undefined True) `seq` ())
    
    230
    +  evaluates to () and not undefined
    
    231
    +
    
    232
    +* If PostfixOperators is ON, then we expand a left section like this:
    
    233
    +      (e `op`)  ==>   op e
    
    234
    +  with no auxiliary function at all.  Simple!
    
    235
    +
    
    236
    +* leftSection and rightSection switch on ImpredicativeTypes locally,
    
    237
    +  during Quick Look; see GHC.Tc.Gen.App.wantQuickLook. Consider
    
    238
    +  test DeepSubsumption08:
    
    239
    +     type Setter st t a b = forall f. Identical f => blah
    
    240
    +     (.~) :: Setter s t a b -> b -> s -> t
    
    241
    +     clear :: Setter a a' b (Maybe b') -> a -> a'
    
    242
    +     clear = (.~ Nothing)
    
    243
    +   The expansion look like (rightSection (.~) Nothing).  So we must
    
    244
    +   instantiate `rightSection` first type argument to a polytype!
    
    245
    +   Hence the special magic in App.wantQuickLook.
    
    246
    +
    
    247
    +Historical Note [Desugaring operator sections]
    
    248
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    249
    +This Note explains some historical trickiness in desugaring left and
    
    250
    +right sections.  That trickiness has completely disappeared now that
    
    251
    +we desugar to calls to 'leftSection` and `rightSection`, but I'm
    
    252
    +leaving it here to remind us how nice the new story is.
    
    253
    +
    
    254
    +Desugaring left sections with -XPostfixOperators is straightforward: convert
    
    255
    +(expr `op`) to (op expr).
    
    256
    +
    
    257
    +Without -XPostfixOperators it's a bit more tricky. At first it looks as if we
    
    258
    +can convert
    
    259
    +
    
    260
    +    (expr `op`)
    
    261
    +
    
    262
    +naively to
    
    263
    +
    
    264
    +    \x -> op expr x
    
    265
    +
    
    266
    +But no!  expr might be a redex, and we can lose laziness badly this
    
    267
    +way.  Consider
    
    268
    +
    
    269
    +    map (expr `op`) xs
    
    270
    +
    
    271
    +for example. If expr were a redex then eta-expanding naively would
    
    272
    +result in multiple evaluations where the user might only have expected one.
    
    273
    +
    
    274
    +So we convert instead to
    
    275
    +
    
    276
    +    let y = expr in \x -> op y x
    
    277
    +
    
    278
    +Also, note that we must do this for both right and (perhaps surprisingly) left
    
    279
    +sections. Why are left sections necessary? Consider the program (found in #18151),
    
    280
    +
    
    281
    +    seq (True `undefined`) ()
    
    282
    +
    
    283
    +according to the Haskell Report this should reduce to () (as it specifies
    
    284
    +desugaring via eta expansion). However, if we fail to eta expand we will rather
    
    285
    +bottom. Consequently, we must eta expand even in the case of a left section.
    
    286
    +
    
    287
    +If `expr` is actually just a variable, say, then the simplifier
    
    288
    +will inline `y`, eliminating the redundant `let`.
    
    289
    +
    
    290
    +Note that this works even in the case that `expr` is unlifted. In this case
    
    291
    +bindNonRec will automatically do the right thing, giving us:
    
    292
    +
    
    293
    +    case expr of y -> (\x -> op y x)
    
    294
    +
    
    295
    +See #18151.
    
    296
    +-}

  • compiler/GHC/Tc/Types/Origin.hs
    ... ... @@ -634,6 +634,7 @@ exprCtOrigin (XExpr (ExpandedThingRn (HSE o _))) = hsCtxtCtOrigin o
    634 634
     exprCtOrigin (XExpr (HsRecSelRn f))  = OccurrenceOfRecSel $ L (getLoc $ foLabel f) (foExt f)
    
    635 635
     
    
    636 636
     hsCtxtCtOrigin :: HsCtxt -> CtOrigin
    
    637
    +hsCtxtCtOrigin (ExprCtxt (ExprWithTySig _ (L _ e) _)) = exprCtOrigin e
    
    637 638
     hsCtxtCtOrigin (ExprCtxt e) = exprCtOrigin e
    
    638 639
     hsCtxtCtOrigin (FunAppCtxt (FunAppCtxtExpr _ e) _) = exprCtOrigin e
    
    639 640
     hsCtxtCtOrigin (StmtErrCtxt{}) = DoStmtOrigin
    

  • testsuite/tests/parser/should_fail/RecordDotSyntaxFail8.stderr
    ... ... @@ -2,11 +2,11 @@ RecordDotSyntaxFail8.hs:47:17: error: [GHC-39999]
    2 2
         • No instance for ‘HasField "quux1" Quux Quux’
    
    3 3
             arising from selecting the field ‘quux1’
    
    4 4
           NB: ‘HasField’ is not the built-in ‘GHC.Internal.Records.HasField’ class.
    
    5
    -    • In the second argument of ‘($)’, namely ‘....bar.baz.quux1’
    
    6
    -      In a stmt of a 'do' block: print @Quux $ ....baz.quux1
    
    5
    +    • In the second argument of ‘($)’, namely ‘a.foo.bar.baz.quux1’
    
    6
    +      In a stmt of a 'do' block: print @Quux $ a.foo.bar.baz.quux1
    
    7 7
           In the expression:
    
    8 8
             do let a = Foo {foo = ...}
    
    9
    -           print @Quux $ ....quux1
    
    9
    +           print @Quux $ ....bar.baz.quux1
    
    10 10
                let b = myQuux
    
    11 11
                print @Quux $ b.quux2
    
    12 12
                let c = Foo {foo = ...}
    
    ... ... @@ -20,7 +20,7 @@ RecordDotSyntaxFail8.hs:50:17: error: [GHC-39999]
    20 20
           In a stmt of a 'do' block: print @Quux $ b.quux2
    
    21 21
           In the expression:
    
    22 22
             do let a = Foo {foo = ...}
    
    23
    -           print @Quux $ ....quux1
    
    23
    +           print @Quux $ ....bar.baz.quux1
    
    24 24
                let b = myQuux
    
    25 25
                print @Quux $ b.quux2
    
    26 26
                let c = Foo {foo = ...}
    
    ... ... @@ -30,11 +30,11 @@ RecordDotSyntaxFail8.hs:53:17: error: [GHC-39999]
    30 30
         • No instance for ‘HasField "quux3" Quux r0’
    
    31 31
             arising from selecting the field ‘quux3’
    
    32 32
           NB: ‘HasField’ is not the built-in ‘GHC.Internal.Records.HasField’ class.
    
    33
    -    • In the second argument of ‘($)’, namely ‘....baz.quux3.wob’
    
    34
    -      In a stmt of a 'do' block: print @Bool $ ....quux3.wob
    
    33
    +    • In the second argument of ‘($)’, namely ‘a.foo.bar.baz.quux3.wob’
    
    34
    +      In a stmt of a 'do' block: print @Bool $ a.foo.bar.baz.quux3.wob
    
    35 35
           In the expression:
    
    36 36
             do let a = Foo {foo = ...}
    
    37
    -           print @Quux $ ....quux1
    
    37
    +           print @Quux $ ....bar.baz.quux1
    
    38 38
                let b = myQuux
    
    39 39
                print @Quux $ b.quux2
    
    40 40
                let c = Foo {foo = ...}
    

  • testsuite/tests/parser/should_fail/RecordDotSyntaxFail9.stderr
    1 1
     RecordDotSyntaxFail9.hs:7:11: error: [GHC-18872]
    
    2 2
         • Couldn't match type ‘Int’ with ‘[Char]’
    
    3 3
             arising from selecting the field ‘foo’
    
    4
    -    • In the expression: a.foo
    
    4
    +    • In the expression: a.foo :: String
    
    5 5
           In a pattern binding: _ = a.foo :: String
    
    6 6
           In a stmt of a 'do' block: let _ = a.foo :: String
    
    7 7