GHC issueshttps://gitlab.haskell.org/ghc/ghc/-/issues2019-07-07T19:11:22Zhttps://gitlab.haskell.org/ghc/ghc/-/issues/1866Extensible Records2019-07-07T19:11:22ZgidynExtensible RecordsThere seems to be widespread agreement that the current situation wrt records is unacceptable, but the official GHC policy is that there are too many good ideas to choose from - so nothing gets done! I hence humbly propose that [http://w...There seems to be widespread agreement that the current situation wrt records is unacceptable, but the official GHC policy is that there are too many good ideas to choose from - so nothing gets done! I hence humbly propose that [http://www.cs.uu.nl/\~daan/download/papers/scopedlabels.pdf](http://www.cs.uu.nl/~daan/download/papers/scopedlabels.pdf) be adapted to GHC. In my naivete, I assume that porting an existing implementation would be much easier than starting from scratch.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | Multiple |
| Architecture | Multiple |
</details>
<!-- {"blocked_by":[],"summary":"Extensible Records","status":"New","operating_system":"Multiple","component":"Compiler","related":[],"milestone":"6.10 branch","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"","keywords":["Extensible","Records"],"differentials":[],"test_case":"","architecture":"Multiple","cc":[""],"type":"FeatureRequest","description":"There seems to be widespread agreement that the current situation wrt records is unacceptable, but the official GHC policy is that there are too many good ideas to choose from - so nothing gets done! I hence humbly propose that [http://www.cs.uu.nl/~daan/download/papers/scopedlabels.pdf] be adapted to GHC. In my naivete, I assume that porting an existing implementation would be much easier than starting from scratch.","type_of_failure":"OtherFailure","blocking":[]} -->6.10 branchhttps://gitlab.haskell.org/ghc/ghc/-/issues/1872Extensible Records2019-07-07T19:11:21ZgidynExtensible RecordsThere seems to be widespread agreement that the current situation with regards to records is unacceptable, but the official GHC policy is that there are too many good ideas to choose from - so nothing gets done!
This ticket is a request...There seems to be widespread agreement that the current situation with regards to records is unacceptable, but the official GHC policy is that there are too many good ideas to choose from - so nothing gets done!
This ticket is a request to implement ExtensibleRecords in GHC.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | Multiple |
| Architecture | Multiple |
</details>
<!-- {"blocked_by":[],"summary":"Extensible Records","status":"New","operating_system":"Multiple","component":"Compiler","related":[],"milestone":"6.10 branch","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"","keywords":["Extensible","Records"],"differentials":[],"test_case":"","architecture":"Multiple","cc":[""],"type":"FeatureRequest","description":"There seems to be widespread agreement that the current situation with regards to records is unacceptable, but the official GHC policy is that there are too many good ideas to choose from - so nothing gets done!\r\n\r\nThis ticket is a request to implement ExtensibleRecords in GHC.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/3632lift restrictions on records with existential fields, especially in the prese...2022-05-26T07:42:13Zeflisterlift restrictions on records with existential fields, especially in the presence of class constraintsthe attached file demos the use of a record with an existential field with a class constraint. it shows several cases where lifting the current restrictions on accessing and updating this field would be both well-defined and useful.
her...the attached file demos the use of a record with an existential field with a class constraint. it shows several cases where lifting the current restrictions on accessing and updating this field would be both well-defined and useful.
here is the record definition; the dur field is existential, but constrained to be in class NoteDur.
```
data Note = forall x . NoteDur x => Note {
midiNum :: Int -- 0-255
, vel :: Int -- 0-255
, chan :: Int -- 0-15
, measure :: Integral a => a
, beat :: Int
, subdiv :: RealFrac a => a -- % of beat
, dur :: x
}
```
here is a walk through of places in the code where the current restrictions are unnecessary and intrusive:
1. lines 64-95 -- these functions wouldn't be necessary if record update syntax were enabled for both existential and non-existential fields. i know 6.12 introduces it for non-existentials, but i don't see why it isn't also possible for existential fields (even without a class constraint). lines 33-35 and 60 show how much nicer it is to use regular updater syntax in this case.
1. Line 142. The same is true for existential accessors when there is a class constraint -- there's no need to restrict this situation because the accessor can have type:
```
fieldName :: (SomeClass x) => Record -> x
```
> line 142 shows a case where this would be very nice to have.
1. line 100 + 107 -- the foralls could be implicit (maybe offer an extention that would allow them to be implicit)
1. lines 134-136 compared to 138-139 show how additional factoring could be achieved if one were allowed to pattern match on the type of an existential with class constraints.
1. lines 124-127 show how it would be nice to have existential classes
1. lastly, allow curried updater functions: `(rec {field = }) 5` instead of `(\x -> (rec {field = x})) 5`8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/5972option to suppress (Monomorphic) record selector functions2021-02-16T11:58:11ZAntCoption to suppress (Monomorphic) record selector functionsThis proposal is a modest step towards freeing up the record fieldname namespace, without in any way pre-judging how the 'narrow namespace issue' might get addressed.
There is to be a compiler flag (suggestion) -XNoMonoRecordFields. (De...This proposal is a modest step towards freeing up the record fieldname namespace, without in any way pre-judging how the 'narrow namespace issue' might get addressed.
There is to be a compiler flag (suggestion) -XNoMonoRecordFields. (Default value ‑XMonoRecordFields, to give H98 behaviour.)
-XNoMonoRecordFields suppresses creating the field selector function from the field name in a record-style data declaration.
Suppressing the function frees up the namespace, to be able to experiment with various record/field approaches -- including the 'cottage industry' of Template Haskell solutions.
In particular, this means we can declare more than one record type within a module using the same field name.
For background, details, use cases, see: http://hackage.haskell.org/trac/ghc/wiki/Records/DeclaredOverloadedRecordFields/NoMonoRecordFields
(Contrast ticket #3356 {-\# LANGUAGE NoTraditionalRecordSyntax \#-}, which suppresses far too much (IMHO).)
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"option to suppress (Monomorphic) record selector functions","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"","keywords":["records"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"This proposal is a modest step towards freeing up the record fieldname namespace, without in any way pre-judging how the 'narrow namespace issue' might get addressed. \r\n\r\n\r\nThere is to be a compiler flag (suggestion) -XNoMonoRecordFields. (Default value ‑XMonoRecordFields, to give H98 behaviour.)\r\n\r\n-XNoMonoRecordFields suppresses creating the field selector function from the field name in a record-style data declaration.\r\n\r\n\r\nSuppressing the function frees up the namespace, to be able to experiment with various record/field approaches -- including the 'cottage industry' of Template Haskell solutions.\r\n\r\n\r\nIn particular, this means we can declare more than one record type within a module using the same field name.\r\n \r\n\r\nFor background, details, use cases, see: http://hackage.haskell.org/trac/ghc/wiki/Records/DeclaredOverloadedRecordFields/NoMonoRecordFields\r\n\r\n(Contrast ticket #3356 {-# LANGUAGE NoTraditionalRecordSyntax #-}, which suppresses far too much (IMHO).)","type_of_failure":"OtherFailure","blocking":[]} -->9.2.1Adam GundryAdam Gundryhttps://gitlab.haskell.org/ghc/ghc/-/issues/9815Runtime error with RecordWildCards and a non-record constructor2019-07-07T18:38:57Ztakano-akioRuntime error with RecordWildCards and a non-record constructorThe following program is accepted with no warning, and crashes at runtime with an error:
```hs
{-# LANGUAGE RecordWildCards #-}
newtype N = N Int deriving (Show)
main = print N{..}
```
```
% runghc wildcards.hs
wildcards.hs: wildcar...The following program is accepted with no warning, and crashes at runtime with an error:
```hs
{-# LANGUAGE RecordWildCards #-}
newtype N = N Int deriving (Show)
main = print N{..}
```
```
% runghc wildcards.hs
wildcards.hs: wildcards.hs:4:14-18: Missing field in record construction
```
I find this behavior surprising. Would it be better to either disallow it or have `-fwarn-missing-fields` warn it?
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.8.3 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Runtime error with RecordWildCards and a non-record constructor","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.8.3","keywords":["RecordWildCards,","warning"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"The following program is accepted with no warning, and crashes at runtime with an error:\r\n\r\n{{{#!hs\r\n{-# LANGUAGE RecordWildCards #-}\r\nnewtype N = N Int deriving (Show)\r\n\r\nmain = print N{..}\r\n}}}\r\n\r\n{{{\r\n% runghc wildcards.hs \r\nwildcards.hs: wildcards.hs:4:14-18: Missing field in record construction\r\n}}}\r\n\r\nI find this behavior surprising. Would it be better to either disallow it or have `-fwarn-missing-fields` warn it?","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/9975RecordWildcards and PatternSynonyms cause impossible bug2021-05-17T16:05:16ZgamegoblinRecordWildcards and PatternSynonyms cause impossible bugWhen using RecordWildcards with PatternSynonyms, I have found a way to cause this bug:
```
$ /usr/local/bin/ghc-7.10.0.20141222 test.hs
[1 of 1] Compiling Main ( test.hs, test.o )
ghc: panic! (the 'impossible' happened)
(...When using RecordWildcards with PatternSynonyms, I have found a way to cause this bug:
```
$ /usr/local/bin/ghc-7.10.0.20141222 test.hs
[1 of 1] Compiling Main ( test.hs, test.o )
ghc: panic! (the 'impossible' happened)
(GHC version 7.10.0.20141222 for x86_64-apple-darwin):
find_tycon
Test
[Test defined at test.hs:6:9,
Test parent:Test defined at test.hs:4:13]
Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug
```
Here is the full code that causes it:
```hs
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE PatternSynonyms #-}
data Test = Test { x :: Int }
pattern Test wat = Test { x = wat }
```
If you remove `RecordWildCards`, the bug does not happen.7.10.1https://gitlab.haskell.org/ghc/ghc/-/issues/10520RecordWildCards causes “is not a (visible) field of constructor” in ghci2019-07-07T18:35:35Zion1RecordWildCards causes “is not a (visible) field of constructor” in ghci```
% ghc -ignore-dot-ghci -e 'data Foo = Bar { baz :: Integer } deriving Show' -e 'Bar 42' -e '(Bar 42){ baz = 43 }' -e 'Bar { baz = 42 }'
Bar {baz = 42}
Bar {baz = 43}
Bar {baz = 42}
```
```
% ghc -ignore-dot-ghci -XRecordWildCards -e...```
% ghc -ignore-dot-ghci -e 'data Foo = Bar { baz :: Integer } deriving Show' -e 'Bar 42' -e '(Bar 42){ baz = 43 }' -e 'Bar { baz = 42 }'
Bar {baz = 42}
Bar {baz = 43}
Bar {baz = 42}
```
```
% ghc -ignore-dot-ghci -XRecordWildCards -e 'data Foo = Bar { baz :: Integer } deriving Show' -e 'Bar 42' -e '(Bar 42){ baz = 43 }' -e 'Bar { baz = 42 }'
Bar {baz = 42}
Bar {baz = 43}
<interactive>:1:7:
‘baz’ is not a (visible) field of constructor ‘Bar’
```
```
% ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.10.1
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.10.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | GHCi |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | hvr |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"RecordWildCards causes “is not a (visible) field of constructor” in ghci","status":"New","operating_system":"","component":"GHCi","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.10.1","keywords":["RecordWildCards"],"differentials":[],"test_case":"","architecture":"","cc":["hvr"],"type":"Bug","description":"{{{\r\n% ghc -ignore-dot-ghci -e 'data Foo = Bar { baz :: Integer } deriving Show' -e 'Bar 42' -e '(Bar 42){ baz = 43 }' -e 'Bar { baz = 42 }'\r\nBar {baz = 42}\r\nBar {baz = 43}\r\nBar {baz = 42}\r\n}}}\r\n\r\n{{{\r\n% ghc -ignore-dot-ghci -XRecordWildCards -e 'data Foo = Bar { baz :: Integer } deriving Show' -e 'Bar 42' -e '(Bar 42){ baz = 43 }' -e 'Bar { baz = 42 }'\r\nBar {baz = 42}\r\nBar {baz = 43}\r\n\r\n<interactive>:1:7:\r\n ‘baz’ is not a (visible) field of constructor ‘Bar’\r\n}}}\r\n\r\n{{{\r\n% ghc --version\r\nThe Glorious Glasgow Haskell Compilation System, version 7.10.1\r\n}}}\r\n","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/11227Interaction between ORF and record pattern synonyms needs to be resolved.2019-07-07T18:31:23ZMatthew PickeringInteraction between ORF and record pattern synonyms needs to be resolved.Currently the two extensions do not work well together. When defining a record pattern synonym all field names must be distinct even with the extension turned on.
<details><summary>Trac metadata</summary>
| Trac field | Val...Currently the two extensions do not work well together. When defining a record pattern synonym all field names must be distinct even with the extension turned on.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.10.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | agundry |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Interaction between ORF and record pattern synonyms needs to be resolved.","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.10.3","keywords":["PatternSynonyms,","orf"],"differentials":[],"test_case":"","architecture":"","cc":["agundry"],"type":"Bug","description":"Currently the two extensions do not work well together. When defining a record pattern synonym all field names must be distinct even with the extension turned on. ","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/11228Interaction between ORF and record pattern synonyms needs to be resolved.2021-02-28T22:10:50ZMatthew PickeringInteraction between ORF and record pattern synonyms needs to be resolved.Currently the two extensions do not work well together. When defining a record pattern synonym all field names must be distinct even with the extension turned on.
<details><summary>Trac metadata</summary>
| Trac field | Val...Currently the two extensions do not work well together. When defining a record pattern synonym all field names must be distinct even with the extension turned on.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.10.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | agundry |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Interaction between ORF and record pattern synonyms needs to be resolved.","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.10.3","keywords":["PatternSynonyms,","orf"],"differentials":[],"test_case":"","architecture":"","cc":["agundry"],"type":"Bug","description":"Currently the two extensions do not work well together. When defining a record pattern synonym all field names must be distinct even with the extension turned on. ","type_of_failure":"OtherFailure","blocking":[]} -->9.2.1Adam GundryAdam Gundryhttps://gitlab.haskell.org/ghc/ghc/-/issues/11343Unable to infer type when using DuplicateRecordFields2020-11-18T09:20:49ZMatthew PickeringUnable to infer type when using DuplicateRecordFieldsIt seems to me that GHC should be able to easily infer the types for the record updates in this simple example. Is there a reason that it is unable to infer the type currently?
```
{-# LANGUAGE OverloadedLabels, DuplicateRecordFields #-...It seems to me that GHC should be able to easily infer the types for the record updates in this simple example. Is there a reason that it is unable to infer the type currently?
```
{-# LANGUAGE OverloadedLabels, DuplicateRecordFields #-}
module C where
main = do
print aThing
print bThing
print (aThing { a = 5 } )
print (bThing { a = 5 } )
data B = B { a :: Int} deriving Show
bThing = B 10
data A = A { a :: Int } deriving Show
aThing = A 10
{-
[1 of 1] Compiling C ( C.hs, C.o )
C.hs:7:10: error:
• Record update is ambiguous, and requires a type signature
• In the first argument of ‘print’, namely ‘(aThing {a = 5})’
In a stmt of a 'do' block: print (aThing {a = 5})
In the expression:
do { print aThing;
print bThing;
print (aThing {a = 5});
print (bThing {a = 5}) }
-}
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.10.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | adamgundry |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Unable to infer type when using DuplicateRecordFields","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.10.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":["adamgundry"],"type":"Bug","description":"It seems to me that GHC should be able to easily infer the types for the record updates in this simple example. Is there a reason that it is unable to infer the type currently?\r\n\r\n{{{\r\n{-# LANGUAGE OverloadedLabels, DuplicateRecordFields #-}\r\nmodule C where\r\n\r\nmain = do\r\n print aThing\r\n print bThing\r\n print (aThing { a = 5 } )\r\n print (bThing { a = 5 } )\r\n\r\ndata B = B { a :: Int} deriving Show\r\n\r\nbThing = B 10\r\n\r\ndata A = A { a :: Int } deriving Show\r\n\r\naThing = A 10\r\n\r\n{-\r\n\r\n[1 of 1] Compiling C ( C.hs, C.o )\r\n\r\nC.hs:7:10: error:\r\n • Record update is ambiguous, and requires a type signature\r\n • In the first argument of ‘print’, namely ‘(aThing {a = 5})’\r\n In a stmt of a 'do' block: print (aThing {a = 5})\r\n In the expression:\r\n do { print aThing;\r\n print bThing;\r\n print (aThing {a = 5});\r\n print (bThing {a = 5}) }\r\n-}\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->Adam GundryAdam Gundryhttps://gitlab.haskell.org/ghc/ghc/-/issues/11809Template Haskell record splices are not renamer-resolved correctly.2019-07-07T18:28:27ZbollmannTemplate Haskell record splices are not renamer-resolved correctly.While working on ticket #8761, I noticed that splicing in record selectors with Template Haskell seems to cause renamer issues in GHC HEAD.
Consider the following TH splice:
```hs
{- Test splicing in a data type with records -}
[d|
da...While working on ticket #8761, I noticed that splicing in record selectors with Template Haskell seems to cause renamer issues in GHC HEAD.
Consider the following TH splice:
```hs
{- Test splicing in a data type with records -}
[d|
data D a = MkD { unD :: a }
someD = MkD "Hello"
getD = unD someD -- unD should resolve to the record selector above!
|]
getD' = unD someD -- dito here outside of the splice!
```
While GHC 7.10.3 accepts this splice and renames it correctly, GHC HEAD fails with the following error message (with `-ddump-splices` enabled):
```
[1 of 1] Compiling Error ( Error.hs, Error.o )
Error.hs:(6,1)-(11,3): Splicing declarations
[d| someD_apF = MkD_apD "Hello"
getD_apG = unD someD_apF
data D_apC a_apH = MkD_apD {unD :: a_apH} |]
======>
data D_a4SA a_a4SD = MkD_a4SB {unD_a4SC :: a_a4SD}
someD_a4Sy = MkD_a4SB "Hello"
getD_a4Sz = unD_a4SC someD_a4Sy
Error.hs:6:1: error:
The exact Name ‘unD_a4SC’ is not in scope
Probable cause: you used a unique Template Haskell name (NameU),
perhaps via newName, but did not bind it
If that's it, then -ddump-splices might be useful
```
I'm not sure as to what introduced this bug, but investigating it I found that the notes
- `NOTE [Binders in Template Haskell] in Convert.hs`, and
- `NOTE [Looking up Exact RdrNames] in RnEnv.hs`
are not respected by function `newRecordSelector` in `rename/RnNames.hs`. I've fixed this function accordingly in [D1940](https://phabricator.haskell.org/D1940) for #8761, but since that patch is not going to be part of 8.0.1, Richard suggested to fix it separately in this ticket.
I'm submitting a patch in due course.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 8.0.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Template Haskell |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Template Haskell record splices are not renamer-resolved correctly.","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"OwnedBy","contents":"bollmann"},"version":"8.0.1","keywords":["Haskell","Records","Renamer","Template"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"While working on ticket #8761, I noticed that splicing in record selectors with Template Haskell seems to cause renamer issues in GHC HEAD.\r\n\r\nConsider the following TH splice:\r\n\r\n{{{#!hs\r\n\r\n{- Test splicing in a data type with records -}\r\n[d|\r\n data D a = MkD { unD :: a }\r\n\r\n someD = MkD \"Hello\"\r\n getD = unD someD -- unD should resolve to the record selector above!\r\n |]\r\n\r\ngetD' = unD someD -- dito here outside of the splice!\r\n}}}\r\n\r\nWhile GHC 7.10.3 accepts this splice and renames it correctly, GHC HEAD fails with the following error message (with `-ddump-splices` enabled):\r\n\r\n{{{\r\n[1 of 1] Compiling Error ( Error.hs, Error.o )\r\nError.hs:(6,1)-(11,3): Splicing declarations\r\n [d| someD_apF = MkD_apD \"Hello\"\r\n getD_apG = unD someD_apF\r\n \r\n data D_apC a_apH = MkD_apD {unD :: a_apH} |]\r\n ======>\r\n data D_a4SA a_a4SD = MkD_a4SB {unD_a4SC :: a_a4SD}\r\n someD_a4Sy = MkD_a4SB \"Hello\"\r\n getD_a4Sz = unD_a4SC someD_a4Sy\r\n\r\nError.hs:6:1: error:\r\n The exact Name ‘unD_a4SC’ is not in scope\r\n Probable cause: you used a unique Template Haskell name (NameU), \r\n perhaps via newName, but did not bind it\r\n If that's it, then -ddump-splices might be useful\r\n}}}\r\n\r\nI'm not sure as to what introduced this bug, but investigating it I found that the notes \r\n\r\n- `NOTE [Binders in Template Haskell] in Convert.hs`, and\r\n- `NOTE [Looking up Exact RdrNames] in RnEnv.hs`\r\n\r\nare not respected by function `newRecordSelector` in `rename/RnNames.hs`. I've fixed this function accordingly in Phab:D1940 for #8761, but since that patch is not going to be part of 8.0.1, Richard suggested to fix it separately in this ticket.\r\n\r\nI'm submitting a patch in due course.","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1bollmannbollmannhttps://gitlab.haskell.org/ghc/ghc/-/issues/12459UnboxedTuple makes overloaded labels fail to parse2019-07-07T18:26:32ZIcelandjackUnboxedTuple makes overloaded labels fail to parse[This](https://gist.githubusercontent.com/PkmX/bfb2c5af4317c96282795f8c588fda1c/raw/4e388fae1b87e16dc215613531e54b036736b34c/NamedTuple.hs) works (removing spaces)
```hs
-- user = ( #login := "themoritz", #id := 3522732 )
user :: User
...[This](https://gist.githubusercontent.com/PkmX/bfb2c5af4317c96282795f8c588fda1c/raw/4e388fae1b87e16dc215613531e54b036736b34c/NamedTuple.hs) works (removing spaces)
```hs
-- user = ( #login := "themoritz", #id := 3522732 )
user :: User
user = (#login := "themoritz", #id := 3522732)
```
but it doesn't when `UnboxedTuples` are enabled:
```hs
-- tWKw.hs:63:46: error: parse error on input ‘)’
user = (#login := "themoritz", #id := 3522732)
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------------- |
| Version | 8.0.1 |
| Type | Bug |
| TypeOfFailure | ValidProgramRejected |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler (Parser) |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"UnboxedTuple makes overloaded labels fail to parse","status":"New","operating_system":"","component":"Compiler (Parser)","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.0.1","keywords":["orf"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"[https://gist.githubusercontent.com/PkmX/bfb2c5af4317c96282795f8c588fda1c/raw/4e388fae1b87e16dc215613531e54b036736b34c/NamedTuple.hs This] works (removing spaces)\r\n\r\n{{{#!hs\r\n-- user = ( #login := \"themoritz\", #id := 3522732 )\r\n\r\nuser :: User\r\nuser = (#login := \"themoritz\", #id := 3522732)\r\n}}}\r\n\r\nbut it doesn't when `UnboxedTuples` are enabled:\r\n\r\n{{{#!hs\r\n-- tWKw.hs:63:46: error: parse error on input ‘)’\r\nuser = (#login := \"themoritz\", #id := 3522732)\r\n}}}\r\n\r\n","type_of_failure":"ValidProgramRejected","blocking":[]} -->8.2.1Adam GundryAdam Gundryhttps://gitlab.haskell.org/ghc/ghc/-/issues/13307Record pattern synonym fields have to be manually exported2023-09-18T06:54:00ZOllie CharlesRecord pattern synonym fields have to be manually exportedThe following currently fails to compile:
```hs
{-# LANGUAGE PatternSynonyms #-}
module A( T( MkT2 ) ) where
data Impl = Impl Int
newtype T = MkT Impl
pattern MkT2 {x} = MkT (Impl x)
{-# LANGUAGE RecordWildCards #-}
module B where
...The following currently fails to compile:
```hs
{-# LANGUAGE PatternSynonyms #-}
module A( T( MkT2 ) ) where
data Impl = Impl Int
newtype T = MkT Impl
pattern MkT2 {x} = MkT (Impl x)
{-# LANGUAGE RecordWildCards #-}
module B where
import A
foo :: T -> Int
foo MkT2{x} = x
```
As far as GHC can see, in module `B`, `MkT2` does not have a field `x`. The fix is to manually export `x` from `A`:
```hs
module A (T(MkT2, x)) where
```
But this is tedious for records with a large amount of fieldshttps://gitlab.haskell.org/ghc/ghc/-/issues/13438ghci :browse does not work with DuplicateRecordFields2023-06-10T12:30:32ZRik van der Kleijghci :browse does not work with DuplicateRecordFieldsUsing `:browse` on module which has enabled DuplicateRecordFields and datatypes are exported, does not return the field accessor functions.
So for example:
```hs
data Login = Login
{ code :: Text
, password :: Text
}
```
`b...Using `:browse` on module which has enabled DuplicateRecordFields and datatypes are exported, does not return the field accessor functions.
So for example:
```hs
data Login = Login
{ code :: Text
, password :: Text
}
```
`browse` for module does not return `code` and `password` accessor functions.BinderDavidBinderDavidhttps://gitlab.haskell.org/ghc/ghc/-/issues/14487Can't Hide Field When DuplicateRecordFields Is Enabled2019-07-07T18:16:50Ziansullivan88Can't Hide Field When DuplicateRecordFields Is EnabledA.hs fails to compile when DuplicateRecordFields is enabled in B.hs.
A.hs
```hs
module A where
import B hiding (duplicateName)
test = X duplicateName
duplicateName = 5
```
B.hs
```hs
{-# LANGUAGE DuplicateRecordFields #...A.hs fails to compile when DuplicateRecordFields is enabled in B.hs.
A.hs
```hs
module A where
import B hiding (duplicateName)
test = X duplicateName
duplicateName = 5
```
B.hs
```hs
{-# LANGUAGE DuplicateRecordFields #-}
module B where
data X = X {
duplicateName :: Int
}
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.0.2 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | lowest |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Can't Hide Field When DuplicateRecordFields Is Enabled","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.0.2","keywords":["DuplicateRecordFields"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"A.hs fails to compile when DuplicateRecordFields is enabled in B.hs.\r\n\r\nA.hs\r\n{{{#!hs\r\nmodule A where\r\n\r\nimport B hiding (duplicateName)\r\n\r\ntest = X duplicateName\r\n\r\nduplicateName = 5\r\n\r\n}}}\r\n\r\nB.hs\r\n{{{#!hs\r\n{-# LANGUAGE DuplicateRecordFields #-}\r\n\r\nmodule B where\r\n\r\ndata X = X {\r\n duplicateName :: Int\r\n}\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->8.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/14549RecordWildCards doesn't work properly in repl2019-07-07T18:16:33ZakegaljRecordWildCards doesn't work properly in repl```hs
Prelude> :set -XRecordWildCards
Prelude> data Test = Test { t1 :: Int, t2 :: Int } deriving Show
Prelude> t1 = 2
Prelude> Test { t2 = 2, ..}
<interactive>:15:1: warning: [-Wmissing-fields]
• Fields of 'Test' not initialised: t...```hs
Prelude> :set -XRecordWildCards
Prelude> data Test = Test { t1 :: Int, t2 :: Int } deriving Show
Prelude> t1 = 2
Prelude> Test { t2 = 2, ..}
<interactive>:15:1: warning: [-Wmissing-fields]
• Fields of 'Test' not initialised: t1
• In the expression: Test {t2 = 2, ..}
In an equation for 'it': it = Test {t2 = 2, ..}
<interactive>:15:1: warning: [-Wmissing-fields]
• Fields of 'Test' not initialised: t1
• In the expression: Test {t2 = 2, ..}
In an equation for 'it': it = Test {t2 = 2, ..}
Test {t1 = *** Exception: <interactive>:15:1-18: Missing field in record construction t1
```
I would expect above to return `Test {t1 = 2, t2 = 2}` instead of throwing an error.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.2.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | lowest |
| Resolution | Unresolved |
| Component | GHCi |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"RecordWildCards doesn't work properly in repl","status":"New","operating_system":"","component":"GHCi","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.2.1","keywords":["recordwildcards","repl,"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"{{{#!hs\r\nPrelude> :set -XRecordWildCards\r\nPrelude> data Test = Test { t1 :: Int, t2 :: Int } deriving Show\r\nPrelude> t1 = 2\r\nPrelude> Test { t2 = 2, ..}\r\n\r\n<interactive>:15:1: warning: [-Wmissing-fields]\r\n • Fields of 'Test' not initialised: t1\r\n • In the expression: Test {t2 = 2, ..}\r\n In an equation for 'it': it = Test {t2 = 2, ..}\r\n\r\n<interactive>:15:1: warning: [-Wmissing-fields]\r\n • Fields of 'Test' not initialised: t1\r\n • In the expression: Test {t2 = 2, ..}\r\n In an equation for 'it': it = Test {t2 = 2, ..}\r\nTest {t1 = *** Exception: <interactive>:15:1-18: Missing field in record construction t1\r\n}}}\r\n\r\n\r\nI would expect above to return `Test {t1 = 2, t2 = 2}` instead of throwing an error.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/14783Initializing record with similarly named field from a different record result...2019-07-07T18:15:38ZulrikrasmussenInitializing record with similarly named field from a different record results in warning rather than errorWhen a record is initialized using a similarly named field from another record, the compiler ignores the initialization and generates a warning instead of throwing an error. I believe this is a bug introduced in GHC 8.0.1 (and probably r...When a record is initialized using a similarly named field from another record, the compiler ignores the initialization and generates a warning instead of throwing an error. I believe this is a bug introduced in GHC 8.0.1 (and probably related to `DuplicateRecordFields`), since earlier versions of GHC would refuse to compile the code.
Consider the following example:
```
-- A.hs
module A where
data A = A { a :: (), b :: () }
-- B.hs
module B where
data B = B { a :: (), b :: () }
-- Main.hs
module Main where
import A hiding (a)
import B
x = A { a = (), b = () }
main = case x of
A () () -> return ()
```
On GHC 8.0.1, this compiles (with a warning), and the program throws an exception when run:
```
$ stack ghc --compiler ghc-8.0.1 -- --make Main.hs
[1 of 3] Compiling B ( B.hs, B.o )
[2 of 3] Compiling A ( A.hs, A.o )
[3 of 3] Compiling Main ( Main.hs, Main.o )
Main.hs:5:7: warning: [-Wmissing-fields]
• Fields of ‘A’ not initialised: a
• In the expression: A {a = (), b = ()}
In an equation for ‘x’: x = A {a = (), b = ()}
Linking Main ...
$ ./Main
Main: Main.hs:5:7-26: Missing field in record construction a
```
On GHC 7.10.3, the program will not compile:
```
$ stack ghc --compiler ghc-7.10.3 -- --make Main.hs
[1 of 3] Compiling B ( B.hs, B.o )
[2 of 3] Compiling A ( A.hs, A.o )
[3 of 3] Compiling Main ( Main.hs, Main.o )
Main.hs:5:7:
Constructor ‘A’ does not have field ‘a’
In the expression: A {a = (), b = ()}
In an equation for ‘x’: x = A {a = (), b = ()}
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.0.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Initializing record with similarly named field from a different record results in warning rather than error","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.0.1","keywords":["DuplicateRecordFields","records"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"When a record is initialized using a similarly named field from another record, the compiler ignores the initialization and generates a warning instead of throwing an error. I believe this is a bug introduced in GHC 8.0.1 (and probably related to `DuplicateRecordFields`), since earlier versions of GHC would refuse to compile the code.\r\n\r\nConsider the following example:\r\n\r\n{{{\r\n-- A.hs\r\nmodule A where\r\n data A = A { a :: (), b :: () }\r\n\r\n-- B.hs\r\nmodule B where\r\n data B = B { a :: (), b :: () }\r\n\r\n-- Main.hs\r\nmodule Main where\r\n import A hiding (a)\r\n import B\r\n\r\n x = A { a = (), b = () }\r\n\r\n main = case x of\r\n A () () -> return ()\r\n}}}\r\n\r\nOn GHC 8.0.1, this compiles (with a warning), and the program throws an exception when run:\r\n\r\n{{{\r\n$ stack ghc --compiler ghc-8.0.1 -- --make Main.hs\r\n[1 of 3] Compiling B ( B.hs, B.o )\r\n[2 of 3] Compiling A ( A.hs, A.o )\r\n[3 of 3] Compiling Main ( Main.hs, Main.o )\r\n\r\nMain.hs:5:7: warning: [-Wmissing-fields]\r\n • Fields of ‘A’ not initialised: a\r\n • In the expression: A {a = (), b = ()}\r\n In an equation for ‘x’: x = A {a = (), b = ()}\r\nLinking Main ...\r\n\r\n$ ./Main \r\nMain: Main.hs:5:7-26: Missing field in record construction a\r\n}}}\r\n\r\nOn GHC 7.10.3, the program will not compile:\r\n{{{\r\n$ stack ghc --compiler ghc-7.10.3 -- --make Main.hs\r\n[1 of 3] Compiling B ( B.hs, B.o )\r\n[2 of 3] Compiling A ( A.hs, A.o )\r\n[3 of 3] Compiling Main ( Main.hs, Main.o )\r\n\r\nMain.hs:5:7:\r\n Constructor ‘A’ does not have field ‘a’\r\n In the expression: A {a = (), b = ()}\r\n In an equation for ‘x’: x = A {a = (), b = ()}\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->8.2.3https://gitlab.haskell.org/ghc/ghc/-/issues/15277Move field name resolution to the type-checker2020-12-03T22:24:34ZAdam GundryMove field name resolution to the type-checkerPer discussion on #15149, we plan to make the type-checker responsible for all field name lookup in record construction, pattern-matching and updates. This should be simpler than the current story and let us get rid of `tcg_field_env`.
...Per discussion on #15149, we plan to make the type-checker responsible for all field name lookup in record construction, pattern-matching and updates. This should be simpler than the current story and let us get rid of `tcg_field_env`.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ----------------------- |
| Version | 8.5 |
| Type | Task |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler (Type checker) |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Move field name resolution to the type-checker","status":"New","operating_system":"","component":"Compiler (Type checker)","related":[],"milestone":"8.8.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.5","keywords":["ORF"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Task","description":"Per discussion on #15149, we plan to make the type-checker responsible for all field name lookup in record construction, pattern-matching and updates. This should be simpler than the current story and let us get rid of `tcg_field_env`.\r\n\r\n","type_of_failure":"OtherFailure","blocking":[]} -->Adam GundryAdam Gundryhttps://gitlab.haskell.org/ghc/ghc/-/issues/15470Record projections with ambiguous types2022-04-08T16:37:22Zsweirich@cis.upenn.eduRecord projections with ambiguous typesThe following code fails
```
{-# LANGUAGE DataKinds, KindSignatures, PolyKinds, TypeFamilies, RankNTypes, AllowAmbiguousTypes #-}
module TypeLambda where
data Fun a b
type family App (f :: Fun t k) (x :: t) :: k
data MONAD m =
MO...The following code fails
```
{-# LANGUAGE DataKinds, KindSignatures, PolyKinds, TypeFamilies, RankNTypes, AllowAmbiguousTypes #-}
module TypeLambda where
data Fun a b
type family App (f :: Fun t k) (x :: t) :: k
data MONAD m =
MONAD
{ return :: forall a. a -> App m a
, (>>=) :: forall a b. App m a -> (a -> App m b) -> App m b
}
```
with the error message
```
TypeLambda.hs:12:5: error:
• Couldn't match type ‘App m b0’ with ‘App m b’
Expected type: App m a -> (a -> App m b) -> App m b
Actual type: App m a -> (a -> App m b0) -> App m b0
NB: ‘App’ is a non-injective type family
The type variable ‘b0’ is ambiguous
• In the expression: (>>=)
In an equation for ‘TypeLambda.>>=’:
(TypeLambda.>>=) MONAD {>>= = (>>=)} = (>>=)
• Relevant bindings include
(>>=) :: forall a b. App m a -> (a -> App m b) -> App m b
(bound at TypeLambda.hs:12:5)
|
12 | , (>>=) :: forall a b. App m a -> (a -> App m b) -> App m b
| ^^^^^
Failed, no modules loaded.
```
However, with ScopedTypeVariables and TypeApplications,
it is possible to define the projections:
```
data MONAD2 m =
MONAD2
(forall a. a -> App m a)
(forall a b. App m a -> (a -> App m b) -> App m b)
bind :: forall b a m. MONAD2 m -> App m a -> (a -> App m b) -> App m b
bind (MONAD2 _ b) = b @a @b
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 8.4.3 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Record projections with ambiguous types","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"8.6.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.4.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"The following code fails\r\n\r\n{{{\r\n{-# LANGUAGE DataKinds, KindSignatures, PolyKinds, TypeFamilies, RankNTypes, AllowAmbiguousTypes #-}\r\n\r\nmodule TypeLambda where\r\n\r\ndata Fun a b \r\n\r\ntype family App (f :: Fun t k) (x :: t) :: k\r\n\r\ndata MONAD m =\r\n MONAD\r\n { return :: forall a. a -> App m a\r\n , (>>=) :: forall a b. App m a -> (a -> App m b) -> App m b\r\n }\r\n}}}\r\n\r\nwith the error message\r\n\r\n{{{\r\nTypeLambda.hs:12:5: error:\r\n • Couldn't match type ‘App m b0’ with ‘App m b’\r\n Expected type: App m a -> (a -> App m b) -> App m b\r\n Actual type: App m a -> (a -> App m b0) -> App m b0\r\n NB: ‘App’ is a non-injective type family\r\n The type variable ‘b0’ is ambiguous\r\n • In the expression: (>>=)\r\n In an equation for ‘TypeLambda.>>=’:\r\n (TypeLambda.>>=) MONAD {>>= = (>>=)} = (>>=)\r\n • Relevant bindings include\r\n (>>=) :: forall a b. App m a -> (a -> App m b) -> App m b\r\n (bound at TypeLambda.hs:12:5)\r\n |\r\n12 | , (>>=) :: forall a b. App m a -> (a -> App m b) -> App m b\r\n | ^^^^^\r\nFailed, no modules loaded.\r\n}}}\r\n\r\nHowever, with ScopedTypeVariables and TypeApplications, \r\nit is possible to define the projections:\r\n\r\n{{{\r\ndata MONAD2 m =\r\n MONAD2\r\n (forall a. a -> App m a)\r\n (forall a b. App m a -> (a -> App m b) -> App m b)\r\n\r\nbind :: forall b a m. MONAD2 m -> App m a -> (a -> App m b) -> App m b\r\nbind (MONAD2 _ b) = b @a @b\r\n}}}\r\n\r\n\r\n","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/16232Add setField to HasField2023-11-24T09:00:48ZAdam GundryAdd setField to HasFieldThis ticket is to track the implementation of https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0042-record-set-field.rst as modified by https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0583-hasfiel...This ticket is to track the implementation of https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0042-record-set-field.rst as modified by https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0583-hasfield-redesign.rst.
The following applies to the old proposal, not all of which is relevant to the new design.
----
I've made a start on the implementation but have a question on which I'd appreciate some input: how should the dictionary for `HasField` be generated?
To recap, recall that at present, `HasField x r a` is coercible to `r -> a` so the dictionary can be constructed merely by taking the selector function for the field and wrapping it in an appropriate coercion.
With the proposal, `HasField x r a` will instead be represented as `r -> (a -> r, a)` where the first component of the tuple is an update function. The problem is how to define this update function in Core. This function should perform case analysis on the record data type, where each case replaces the value of the field being updated and preserves all the other fields. For example, given a data type `data T = MkT { foo :: Int, bar :: Bool }` we need to generate
```hs
\ r x -> case r of MkT {foo = _, bar = bar} -> MkT { foo = x, bar = bar }
```
The most obvious approach is to generate well-typed Core for the update function directly, but this seems to be rather complex, in particular because of the worker/wrapper distinction, as one ends up reconstructing much of the typechecking/desugaring for record pattern matching and construction. This also seems like a lot of work to do every time a `HasField` constraint is solved.
Would it be reasonable to generate update functions for fields at definition sites, as we do for selector functions? I've implemented this in the past, and it is relatively simple to generate renamed syntax to feed in to the type-checker. However, this would add some overhead for every field, even if `HasField` was not subsequently used, and would require some naming scheme for update functions.
Or are there other options? Is there some way to solve a `HasField` constraint and construct its dictionary by emitting renamed syntax for subsequent type-checking, such that subsequently solving similar constraints will use the same dictionary?
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ----------------------- |
| Version | 8.7 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler (Type checker) |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | NeilMitchell, simonpj |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Add setField to HasField","status":"New","operating_system":"","component":"Compiler (Type checker)","related":[],"milestone":"8.10.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.7","keywords":["ORF"],"differentials":[],"test_case":"","architecture":"","cc":["NeilMitchell","simonpj"],"type":"FeatureRequest","description":"This ticket is to track the implementation of https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0042-record-set-field.rst\r\n\r\nI've made a start on the implementation but have a question on which I'd appreciate some input: how should the dictionary for `HasField` be generated?\r\n\r\nTo recap, recall that at present, `HasField x r a` is coercible to `r -> a` so the dictionary can be constructed merely by taking the selector function for the field and wrapping it in an appropriate coercion.\r\n\r\nWith the proposal, `HasField x r a` will instead be represented as `r -> (a -> r, a)` where the first component of the tuple is an update function. The problem is how to define this update function in Core. This function should perform case analysis on the record data type, where each case replaces the value of the field being updated and preserves all the other fields. For example, given a data type `data T = MkT { foo :: Int, bar :: Bool }` we need to generate\r\n{{{#!hs\r\n\\ r x -> case r of MkT {foo = _, bar = bar} -> MkT { foo = x, bar = bar }\r\n}}}\r\n\r\nThe most obvious approach is to generate well-typed Core for the update function directly, but this seems to be rather complex, in particular because of the worker/wrapper distinction, as one ends up reconstructing much of the typechecking/desugaring for record pattern matching and construction. This also seems like a lot of work to do every time a `HasField` constraint is solved.\r\n\r\nWould it be reasonable to generate update functions for fields at definition sites, as we do for selector functions? I've implemented this in the past, and it is relatively simple to generate renamed syntax to feed in to the type-checker. However, this would add some overhead for every field, even if `HasField` was not subsequently used, and would require some naming scheme for update functions.\r\n\r\nOr are there other options? Is there some way to solve a `HasField` constraint and construct its dictionary by emitting renamed syntax for subsequent type-checking, such that subsequently solving similar constraints will use the same dictionary?","type_of_failure":"OtherFailure","blocking":[]} -->