Hannes Siebenhandl pushed to branch wip/fendor/has-field-hie at Glasgow Haskell Compiler / GHC

Commits:

7 changed files:

Changes:

  • compiler/GHC/Iface/Ext/Ast.hs
    ... ... @@ -22,11 +22,11 @@ import GHC.Core.Utils (exprType)
    22 22
     import GHC.Core.TyCo.Rep (Type(TyConApp))
    
    23 23
     import GHC.Core.TyCon (TyCon(..))
    
    24 24
     import GHC.Core.ConLike           ( conLikeName )
    
    25
    -import GHC.Core.DataCon           ( dataConWrapperType )
    
    25
    +import GHC.Core.DataCon           ( dataConWrapperType, dataConTyCon )
    
    26 26
     import GHC.Core.Type              ( Type, ForAllTyFlag(..) )
    
    27
    -import GHC.Core.TyCon             ( TyCon, tyConClass_maybe )
    
    27
    +import GHC.Core.TyCon             ( TyCon, tyConClass_maybe, isClassTyCon )
    
    28 28
     import GHC.Core.InstEnv
    
    29
    -import GHC.Core.Predicate         ( isEvId )
    
    29
    +import GHC.Core.Predicate         ( isEvId, getClassPredTys_maybe )
    
    30 30
     
    
    31 31
     import GHC.Hs
    
    32 32
     import GHC.Hs.Syn.Type
    
    ... ... @@ -36,12 +36,12 @@ import GHC.Types.Basic
    36 36
     import GHC.Types.UnresolvedImport ( isGeneratedImport )
    
    37 37
     import GHC.Types.FieldLabel
    
    38 38
     import GHC.Types.Avail            ( Avails )
    
    39
    -import GHC.Types.Id               ( isDataConId_maybe )
    
    39
    +import GHC.Types.Id               ( isDataConId_maybe, isRecordSelector )
    
    40 40
     import GHC.Types.Name             ( Name, nameSrcSpan, nameUnique, wiredInNameTyThing_maybe, getName, hasKnownKey )
    
    41 41
     import GHC.Types.Name.Env         ( NameEnv, emptyNameEnv, extendNameEnv, lookupNameEnv )
    
    42 42
     import GHC.Types.Name.Reader      ( RecFieldInfo(..), WithUserRdr(..) )
    
    43 43
     import GHC.Types.SrcLoc
    
    44
    -import GHC.Types.Var              ( Id, Var, EvId, varName, varType, varUnique )
    
    44
    +import GHC.Types.Var              ( Id, Var, EvId, varName, varType, varUnique, isId )
    
    45 45
     import GHC.Types.Var.Env
    
    46 46
     import GHC.Types.Var.FV
    
    47 47
     
    
    ... ... @@ -684,9 +684,73 @@ instance ToHie (Context (Located Name)) where
    684 684
     instance ToHie (Context (Located (WithUserRdr Name))) where
    
    685 685
       toHie (C c (L l (WithUserRdr _ n))) = toHie $ C c (L l n)
    
    686 686
     
    
    687
    -hieEvIdsOfTerm :: EvTerm -> [EvId]
    
    688
    --- Returns only EvIds satisfying relevantEvId
    
    689
    -hieEvIdsOfTerm = runFVSelectiveList isEvId . evTermFVs
    
    687
    +{- Note [Evidence dependencies in HIE files]
    
    688
    +   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    689
    +The 'EvBindDeps' of an 'EvLetBind' record what a dictionary was built out of,
    
    690
    +so that a tool can answer "where does the evidence for this constraint come
    
    691
    +from?" by walking 'getEvidenceTree' (in GHC.Iface.Ext.Utils).  For that to be
    
    692
    +useful, the dependencies have to /discriminate/ one solution from another.  So
    
    693
    +we make two adjustments to the plain free evidence variables of the right hand
    
    694
    +side:
    
    695
    +
    
    696
    +(1) We drop the data constructor of a class dictionary, e.g. @C:HasField@.
    
    697
    +    These do satisfy 'isEvId', but they /construct/ a dictionary rather than
    
    698
    +    being evidence in their own right, and which one appears is already
    
    699
    +    determined by the constraint being solved.  Reporting one tells a user
    
    700
    +    nothing they did not know from the constraint they hovered over, and is
    
    701
    +    actively misleading: it points into the module defining the /class/,
    
    702
    +    rather than at whatever provided the instance.
    
    703
    +
    
    704
    +(2) We keep record selectors, which are not evidence and so do not satisfy
    
    705
    +    'isEvId'.  When a constraint is solved by a built-in rule that builds the
    
    706
    +    dictionary out of a record selector instead of applying a dictionary
    
    707
    +    function, that selector plays exactly the role the dictionary function
    
    708
    +    would, and is the only thing recording /which/ instance was used.  Such a
    
    709
    +    selector is additionally recorded as an 'EvInstBind' for the constraint's
    
    710
    +    own class, so that 'getEvidenceTree' describes it as providing the
    
    711
    +    instance instead of falling through to its "external evidence variable"
    
    712
    +    case (which is what it reports for a dependency it can find no evidence
    
    713
    +    binding for).
    
    714
    +
    
    715
    +@HasField@ is what motivates both rules: a constraint @HasField "fld" T Int@
    
    716
    +for a real record field is solved by building @MkHasField (fld |> co)@ -- see
    
    717
    +Note [HasField instances] in GHC.Tc.Instance.Class -- so without (1) and (2)
    
    718
    +the evidence for every record selection, however different, bottomed out at
    
    719
    +@GHC.Internal.Records.C:HasField@.  Neither rule names @HasField@, though, and
    
    720
    +neither should: they say "a dictionary constructor explains nothing" and "a
    
    721
    +selector used as evidence explains something", which holds for any class
    
    722
    +solved this way.
    
    723
    +
    
    724
    +The 'EvInstBind' of (2) is deliberately recorded at the span of the /evidence
    
    725
    +binding/, not at the selector's own 'nameSrcSpan'.  Attaching an evidence
    
    726
    +context to the field's declaration would merge it into the
    
    727
    +'IdentifierDetails' of the declaration itself, and consumers reasonably skip
    
    728
    +identifiers mentioning evidence when deciding what a source token refers to --
    
    729
    +Haddock's hyperlinked source would then stop linking the field declaration.
    
    730
    +The 'Name' recorded is the selector either way, which is what an IDE needs in
    
    731
    +order to navigate to it.
    
    732
    +-}
    
    733
    +
    
    734
    +-- | Is this the data constructor of a class dictionary, e.g. @C:HasField@?
    
    735
    +--
    
    736
    +-- See Note [Evidence dependencies in HIE files]
    
    737
    +isClassDataConId :: Id -> Bool
    
    738
    +isClassDataConId v
    
    739
    +  | Just dc <- isDataConId_maybe v = isClassTyCon (dataConTyCon dc)
    
    740
    +  | otherwise                      = False
    
    741
    +
    
    742
    +hieEvIdsOfTerm :: EvTerm -> [Var]
    
    743
    +-- See Note [Evidence dependencies in HIE files]
    
    744
    +hieEvIdsOfTerm = runFVSelectiveList relevant . evTermFVs
    
    745
    +  where
    
    746
    +    -- NB: this traversal offers us TyVars as well as Ids, and 'idDetails'
    
    747
    +    -- panics on a TyVar, so the Id-only predicates must be guarded by
    
    748
    +    -- 'isId'.  'isEvId' only looks at the type and is safe on either; it
    
    749
    +    -- deliberately admits coercion variables, which are TyVars.
    
    750
    +    relevant v
    
    751
    +      | not (isId v) = isEvId v
    
    752
    +      | otherwise    = (isEvId v && not (isClassDataConId v))
    
    753
    +                    || isRecordSelector v
    
    690 754
     
    
    691 755
     instance ToHie (EvBindContext (LocatedA TcEvBinds)) where
    
    692 756
       toHie (EvBindContext sc sp (L span (EvBinds bs)))
    
    ... ... @@ -699,6 +763,13 @@ instance ToHie (EvBindContext (LocatedA TcEvBinds)) where
    699 763
                 [ toHie (C (EvidenceVarBind (EvLetBind depNames) (combineScopes sc (mkScope span)) sp)
    
    700 764
                                             (L span $ eb_lhs evbind))
    
    701 765
                 , toHie $ map (C EvidenceVarUse . L span) $ evDeps
    
    766
    +              -- See Note [Evidence dependencies in HIE files]
    
    767
    +            , toHie [ C (EvidenceVarBind (EvInstBind False (className cls))
    
    768
    +                                         ModuleScope Nothing)
    
    769
    +                        (L span sel)
    
    770
    +                    | Just (cls, _) <- [getClassPredTys_maybe (varType (eb_lhs evbind))]
    
    771
    +                    , sel <- evDeps
    
    772
    +                    , isId sel, isRecordSelector sel ]
    
    702 773
                 ]
    
    703 774
       toHie _ = pure []
    
    704 775
     
    

  • compiler/GHC/Rename/Expr.hs
    ... ... @@ -431,7 +431,7 @@ rnExpr (HsProjection _ fs)
    431 431
            ; let fs' = NE.map rnDotFieldOcc fs
    
    432 432
            ; return ( mkExpandedExpr
    
    433 433
                         (HsProjection noExtField fs')
    
    434
    -                    (mkProjection getField circ $ NE.map (unLoc . dfoLabel) fs')
    
    434
    +                    (mkProjection getField circ $ NE.map dfoLabel fs')
    
    435 435
                     , unitFN circ `plusFN` fv_getField) }
    
    436 436
     
    
    437 437
     ------------------------------------------
    
    ... ... @@ -2916,14 +2916,24 @@ mkSet set_field acc (field, g) = wrapGenSpan (mkSetField set_field g field acc)
    2916 2916
     -- mkProjection fields calculates a projection.
    
    2917 2917
     -- e.g. .x = mkProjection [x] = getField @"x"
    
    2918 2918
     --      .x.y = mkProjection [.x, .y] = (.y) . (.x) = getField @"y" . getField @"x"
    
    2919
    -mkProjection :: Name -> Name -> NonEmpty FieldLabelString -> HsExpr GhcRn
    
    2920
    -mkProjection getFieldName circName (field :| fields) = foldl' f (proj field) fields
    
    2919
    +mkProjection :: Name -> Name -> NonEmpty (XRec GhcRn FieldLabelString)
    
    2920
    +             -> HsExpr GhcRn
    
    2921
    +mkProjection getFieldName circName (field :| fields)
    
    2922
    +  = unLoc $ foldl' f (proj field) fields
    
    2921 2923
       where
    
    2922
    -    f :: HsExpr GhcRn -> FieldLabelString -> HsExpr GhcRn
    
    2923
    -    f acc field = genHsApps circName $ map wrapGenSpan [proj field, acc]
    
    2924
    -
    
    2925
    -    proj :: FieldLabelString -> HsExpr GhcRn
    
    2926
    -    proj (FieldLabelString f) = genHsVar getFieldName `genAppType` genHsTyLit f
    
    2924
    +    f :: LHsExpr GhcRn -> XRec GhcRn FieldLabelString -> LHsExpr GhcRn
    
    2925
    +    f acc field = wrapGenSpan $ genHsApps circName [proj field, acc]
    
    2926
    +
    
    2927
    +    -- Give each `getField` the SrcSpan of the label it projects, so that the
    
    2928
    +    -- HasField evidence for that label can be found at the label itself.
    
    2929
    +    -- Without this a multi-label section like (.x.y) has no usable span
    
    2930
    +    -- anywhere inside it, and the whole section shows no type and no
    
    2931
    +    -- evidence at all.
    
    2932
    +    -- See Note [Source locations for implicit function calls] in GHC.Iface.Ext.Ast
    
    2933
    +    proj :: XRec GhcRn FieldLabelString -> LHsExpr GhcRn
    
    2934
    +    proj lfield@(L _ (FieldLabelString f))
    
    2935
    +      = wrapGenSpan' (getHasLoc lfield)
    
    2936
    +      $ genHsVar getFieldName `genAppType` genHsTyLit f
    
    2927 2937
     
    
    2928 2938
     -- mkProjUpdateSetField calculates functions representing dot notation record updates.
    
    2929 2939
     -- e.g. Suppose an update like foo.bar = 1.
    

  • testsuite/tests/hiefile/should_run/HasFieldQueries.hs
    ... ... @@ -29,6 +29,16 @@ nestedNoSig n = n.nested1.field2 :: Bool
    29 29
     --                         ^ this is the point
    
    30 30
     
    
    31 31
     
    
    32
    +-- Multi-label projection sections: each getField gets the SrcSpan of its own
    
    33
    +-- field label, so both HasField dictionaries are reachable.  Before that, no
    
    34
    +-- node inside the section had a usable span and hovering it found nothing at
    
    35
    +-- all.  The points below are on 'nested1' and 'field1' respectively.
    
    36
    +projSection :: NestedThing -> Char
    
    37
    +projSection = (.nested1.field1)
    
    38
    +
    
    39
    +projSectionApplied :: NestedThing -> Char
    
    40
    +projSectionApplied n = (.nested1.field1) n
    
    41
    +
    
    32 42
     
    
    33 43
     points =
    
    34 44
       [ (13,17)
    
    ... ... @@ -38,6 +48,10 @@ points =
    38 48
       , (23,25)
    
    39 49
       , (27,20)
    
    40 50
       , (27,28)
    
    51
    +  , (37,17)
    
    52
    +  , (37,25)
    
    53
    +  , (40,26)
    
    54
    +  , (40,34)
    
    41 55
       ]
    
    42 56
     
    
    43 57
     main = do
    

  • testsuite/tests/hiefile/should_run/HasFieldQueries.stdout
    ... ... @@ -3,16 +3,18 @@ At point (13,17), we found:
    3 3
     ==========================
    
    4 4
     
    
    5 5
     │ $dHasField at HasFieldQueries.hs:1:1, of type: HasField "field1" Thing Char
    
    6
    -│     is an evidence variable bound by a let, depending on: [C:HasField]
    
    6
    +│     is an evidence variable bound by a let, depending on: [field1]
    
    7 7
     │           with scope: ModuleScope
    
    8 8
     
    
    9 9
     │     Defined at <no location info>
    
    10 10
     
    
    11 11
     |
    
    12 12
     `- ┌
    
    13
    -   │ C:HasField at HasFieldQueries.hs:1:1, of type: forall {k} (x :: k) r a. (r -> a) -> HasField x r a
    
    14
    -   │     is a usage of an external evidence variable
    
    15
    -   │     Defined in `GHC.Internal.Records'
    
    13
    +   │ field1 at HasFieldQueries.hs:1:1, of type: Thing -> Char
    
    14
    +   │     is an evidence variable bound by an instance of class HasField
    
    15
    +   │           with scope: ModuleScope
    
    16
    +
    
    17
    +   │     Defined at HasFieldQueries.hs:9:21
    
    16 18
     
    
    17 19
     
    
    18 20
     ==========================
    
    ... ... @@ -23,16 +25,18 @@ At point (16,27), we found:
    23 25
     ==========================
    
    24 26
     
    
    25 27
     │ $dHasField at HasFieldQueries.hs:16:1-32, of type: HasField "field1" Thing Char
    
    26
    -│     is an evidence variable bound by a let, depending on: [C:HasField]
    
    28
    +│     is an evidence variable bound by a let, depending on: [field1]
    
    27 29
     │           with scope: LocalScope HasFieldQueries.hs:16:1-32
    
    28 30
     │           bound at: HasFieldQueries.hs:16:1-32
    
    29 31
     │     Defined at <no location info>
    
    30 32
     
    
    31 33
     |
    
    32 34
     `- ┌
    
    33
    -   │ C:HasField at HasFieldQueries.hs:1:1, of type: forall {k} (x :: k) r a. (r -> a) -> HasField x r a
    
    34
    -   │     is a usage of an external evidence variable
    
    35
    -   │     Defined in `GHC.Internal.Records'
    
    35
    +   │ field1 at HasFieldQueries.hs:1:1, of type: Thing -> Char
    
    36
    +   │     is an evidence variable bound by an instance of class HasField
    
    37
    +   │           with scope: ModuleScope
    
    38
    +
    
    39
    +   │     Defined at HasFieldQueries.hs:9:21
    
    36 40
     
    
    37 41
     
    
    38 42
     ==========================
    
    ... ... @@ -40,16 +44,18 @@ At point (23,17), we found:
    40 44
     ==========================
    
    41 45
     
    
    42 46
     │ $dHasField at HasFieldQueries.hs:1:1, of type: HasField "nested1" NestedThing Thing
    
    43
    -│     is an evidence variable bound by a let, depending on: [C:HasField]
    
    47
    +│     is an evidence variable bound by a let, depending on: [nested1]
    
    44 48
     │           with scope: ModuleScope
    
    45 49
     
    
    46 50
     │     Defined at <no location info>
    
    47 51
     
    
    48 52
     |
    
    49 53
     `- ┌
    
    50
    -   │ C:HasField at HasFieldQueries.hs:1:1, of type: forall {k} (x :: k) r a. (r -> a) -> HasField x r a
    
    51
    -   │     is a usage of an external evidence variable
    
    52
    -   │     Defined in `GHC.Internal.Records'
    
    54
    +   │ nested1 at HasFieldQueries.hs:1:1, of type: NestedThing -> Thing
    
    55
    +   │     is an evidence variable bound by an instance of class HasField
    
    56
    +   │           with scope: ModuleScope
    
    57
    +
    
    58
    +   │     Defined at HasFieldQueries.hs:20:34
    
    53 59
     
    
    54 60
     
    
    55 61
     ==========================
    
    ... ... @@ -57,17 +63,27 @@ At point (23,25), we found:
    57 63
     ==========================
    
    58 64
     
    
    59 65
     │ $dHasField at HasFieldQueries.hs:1:1, of type: HasField "field1" Thing Char
    
    60
    -│     is an evidence variable bound by a let, depending on: [C:HasField]
    
    66
    +│     is an evidence variable bound by a let, depending on: [$dHasField]
    
    61 67
     │           with scope: ModuleScope
    
    62 68
     
    
    63 69
     │     Defined at <no location info>
    
    64 70
     
    
    65 71
     |
    
    66 72
     `- ┌
    
    67
    -   │ C:HasField at HasFieldQueries.hs:1:1, of type: forall {k} (x :: k) r a. (r -> a) -> HasField x r a
    
    68
    -   │     is a usage of an external evidence variable
    
    69
    -   │     Defined in `GHC.Internal.Records'
    
    73
    +   │ $dHasField at HasFieldQueries.hs:1:1, of type: HasField "field1" Thing Char
    
    74
    +   │     is an evidence variable bound by a let, depending on: [field1]
    
    75
    +   │           with scope: ModuleScope
    
    76
    +
    
    77
    +   │     Defined at <no location info>
    
    70 78
     
    
    79
    +   |
    
    80
    +   `- ┌
    
    81
    +      │ field1 at HasFieldQueries.hs:1:1, of type: Thing -> Char
    
    82
    +      │     is an evidence variable bound by an instance of class HasField
    
    83
    +      │           with scope: ModuleScope
    
    84
    +
    
    85
    +      │     Defined at HasFieldQueries.hs:9:21
    
    86
    +
    
    71 87
     
    
    72 88
     ==========================
    
    73 89
     At point (27,20), we found:
    
    ... ... @@ -107,3 +123,87 @@ At point (27,28), we found:
    107 123
        │     Defined at <no location info>
    
    108 124
     
    
    109 125
     
    
    126
    +==========================
    
    127
    +At point (37,17), we found:
    
    128
    +==========================
    
    129
    +
    
    130
    +│ $dHasField at HasFieldQueries.hs:1:1, of type: HasField "nested1" NestedThing Thing
    
    131
    +│     is an evidence variable bound by a let, depending on: [nested1]
    
    132
    +│           with scope: ModuleScope
    
    133
    +
    
    134
    +│     Defined at <no location info>
    
    135
    +
    
    136
    +|
    
    137
    +`- ┌
    
    138
    +   │ nested1 at HasFieldQueries.hs:1:1, of type: NestedThing -> Thing
    
    139
    +   │     is an evidence variable bound by an instance of class HasField
    
    140
    +   │           with scope: ModuleScope
    
    141
    +
    
    142
    +   │     Defined at HasFieldQueries.hs:20:34
    
    143
    +
    
    144
    +
    
    145
    +==========================
    
    146
    +At point (37,25), we found:
    
    147
    +==========================
    
    148
    +
    
    149
    +│ $dHasField at HasFieldQueries.hs:1:1, of type: HasField "field1" Thing Char
    
    150
    +│     is an evidence variable bound by a let, depending on: [$dHasField]
    
    151
    +│           with scope: ModuleScope
    
    152
    +
    
    153
    +│     Defined at <no location info>
    
    154
    +
    
    155
    +|
    
    156
    +`- ┌
    
    157
    +   │ $dHasField at HasFieldQueries.hs:1:1, of type: HasField "field1" Thing Char
    
    158
    +   │     is an evidence variable bound by a let, depending on: [field1]
    
    159
    +   │           with scope: ModuleScope
    
    160
    +
    
    161
    +   │     Defined at <no location info>
    
    162
    +
    
    163
    +   |
    
    164
    +   `- ┌
    
    165
    +      │ field1 at HasFieldQueries.hs:1:1, of type: Thing -> Char
    
    166
    +      │     is an evidence variable bound by an instance of class HasField
    
    167
    +      │           with scope: ModuleScope
    
    168
    +
    
    169
    +      │     Defined at HasFieldQueries.hs:9:21
    
    170
    +
    
    171
    +
    
    172
    +==========================
    
    173
    +At point (40,26), we found:
    
    174
    +==========================
    
    175
    +
    
    176
    +│ $dHasField at HasFieldQueries.hs:1:1, of type: HasField "nested1" NestedThing Thing
    
    177
    +│     is an evidence variable bound by a let, depending on: [nested1]
    
    178
    +│           with scope: ModuleScope
    
    179
    +
    
    180
    +│     Defined at <no location info>
    
    181
    +
    
    182
    +|
    
    183
    +`- ┌
    
    184
    +   │ nested1 at HasFieldQueries.hs:1:1, of type: NestedThing -> Thing
    
    185
    +   │     is an evidence variable bound by an instance of class HasField
    
    186
    +   │           with scope: ModuleScope
    
    187
    +
    
    188
    +   │     Defined at HasFieldQueries.hs:20:34
    
    189
    +
    
    190
    +
    
    191
    +==========================
    
    192
    +At point (40,34), we found:
    
    193
    +==========================
    
    194
    +
    
    195
    +│ $dHasField at HasFieldQueries.hs:1:1, of type: HasField "field1" Thing Char
    
    196
    +│     is an evidence variable bound by a let, depending on: [field1]
    
    197
    +│           with scope: ModuleScope
    
    198
    +
    
    199
    +│     Defined at <no location info>
    
    200
    +
    
    201
    +|
    
    202
    +`- ┌
    
    203
    +   │ field1 at HasFieldQueries.hs:1:1, of type: Thing -> Char
    
    204
    +   │     is an evidence variable bound by an instance of class HasField
    
    205
    +   │           with scope: ModuleScope
    
    206
    +
    
    207
    +   │     Defined at HasFieldQueries.hs:9:21
    
    208
    +
    
    209
    +

  • testsuite/tests/overloadedrecflds/should_fail/RecordDotErrCtxt.hs
    1
    +{-# LANGUAGE OverloadedRecordDot #-}
    
    2
    +
    
    3
    +-- The renamer expands @e.fld@ to @getField \@"fld" e@ (mkGetField in
    
    4
    +-- GHC.Rename.Expr).  For the sake of .hie files the application head of that
    
    5
    +-- expansion carries the SrcSpan of the field label, but it must be a
    
    6
    +-- *generated* span (@GeneratedSrcSpan (OrigSpan ...)@, built by wrapGenSpan')
    
    7
    +-- rather than a plain RealSrcSpan, or else isGeneratedSrcSpan is False and
    
    8
    +-- GHC.Tc.Gen.App starts reporting the internal 'getField' to the user.
    
    9
    +--
    
    10
    +-- The CtOrigin site (mk_origin) is already covered by T26480b, which contrasts
    
    11
    +-- an explicit 'getField' ("arising from a use of `getField'") with record dot
    
    12
    +-- syntax ("arising from selecting the field `x'"); see also T19843h and
    
    13
    +-- RecordDotSyntaxFail8.  The result-type site is covered by
    
    14
    +-- RecordDotSyntaxFail9.
    
    15
    +--
    
    16
    +-- What is *not* covered anywhere else is addArgCtxt (GHC.Tc.Gen.App), which
    
    17
    +-- needs an ill-typed argument underneath the selection.  With a real head span
    
    18
    +-- the second error below would gain a
    
    19
    +--     "In the first argument of `getField', namely `('c' + 1)'"
    
    20
    +-- context line.
    
    21
    +module RecordDotErrCtxt where
    
    22
    +
    
    23
    +data T = MkT { fld :: Int }
    
    24
    +
    
    25
    +argCtxt :: Int
    
    26
    +argCtxt = ('c' + 1).fld

  • testsuite/tests/overloadedrecflds/should_fail/RecordDotErrCtxt.stderr
    1
    +RecordDotErrCtxt.hs:26:11: error: [GHC-39999]
    
    2
    +    • No instance for ‘GHC.Internal.Records.HasField "fld" Char Int’
    
    3
    +        arising from selecting the field ‘fld’
    
    4
    +      NB: ‘Char’ is not a record type.
    
    5
    +    • In the expression: ('c' + 1).fld
    
    6
    +      In an equation for ‘argCtxt’: argCtxt = ('c' + 1).fld
    
    7
    +
    
    8
    +RecordDotErrCtxt.hs:26:16: error: [GHC-39999]
    
    9
    +    • No instance for ‘Num Char’ arising from a use of ‘+’
    
    10
    +    • In the expression: 'c' + 1
    
    11
    +      In the expression: ('c' + 1).fld
    
    12
    +      In an equation for ‘argCtxt’: argCtxt = ('c' + 1).fld
    
    13
    +

  • testsuite/tests/overloadedrecflds/should_fail/all.T
    ... ... @@ -63,3 +63,4 @@ test('T23010_fail', [extra_files(['T23010_fail.hs-boot', 'T23010_fail_aux.hs'])]
    63 63
                       , multimod_compile_fail
    
    64 64
                       , ['T23010_fail T23010_fail_aux', '-v0'])
    
    65 65
     test('T23063', extra_files(['T23063_aux.hs']), multimod_compile_fail, ['T23063', '-v0'])
    
    66
    +test('RecordDotErrCtxt', normal, compile_fail, [''])