Oleg Grenrus pushed to branch wip/T26295 at Glasgow Haskell Compiler / GHC
Commits:
-
a6237d55
by Oleg Grenrus at 2025-08-11T12:23:01+03:00
4 changed files:
- compiler/GHC/Tc/Validity.hs
- + testsuite/tests/overloadedrecflds/should_run/T26295.hs
- + testsuite/tests/overloadedrecflds/should_run/T26295.stdout
- testsuite/tests/overloadedrecflds/should_run/all.T
Changes:
... | ... | @@ -31,6 +31,7 @@ import GHC.Tc.Instance.Family |
31 | 31 | import GHC.Tc.Types.Origin
|
32 | 32 | import GHC.Tc.Types.Rank
|
33 | 33 | import GHC.Tc.Errors.Types
|
34 | +import GHC.Tc.Utils.Env (tcLookupId)
|
|
34 | 35 | import GHC.Tc.Utils.TcType
|
35 | 36 | import GHC.Tc.Utils.Monad
|
36 | 37 | import GHC.Tc.Zonk.TcType
|
... | ... | @@ -60,6 +61,8 @@ import qualified GHC.LanguageExtensions as LangExt |
60 | 61 | import GHC.Types.Error
|
61 | 62 | import GHC.Types.Basic ( TypeOrKind(..), UnboxedTupleOrSum(..)
|
62 | 63 | , unboxedTupleOrSumExtension )
|
64 | +import GHC.Types.Id (isNaughtyRecordSelector)
|
|
65 | +import GHC.Types.FieldLabel (flSelector)
|
|
63 | 66 | import GHC.Types.Name
|
64 | 67 | import GHC.Types.Var.Env
|
65 | 68 | import GHC.Types.Var.Set
|
... | ... | @@ -1718,8 +1721,17 @@ checkHasFieldInst cls tys@[_k_ty, _r_rep, _a_rep, lbl_ty, r_ty, _a_ty] = |
1718 | 1721 | | otherwise -> case isStrLitTy lbl_ty of
|
1719 | 1722 | Just lbl
|
1720 | 1723 | | let lbl_str = FieldLabelString lbl
|
1721 | - , isJust (lookupTyConFieldLabel lbl_str tc)
|
|
1722 | - -> add_err $ IllegalHasFieldInstanceTyConHasField tc lbl_str
|
|
1724 | + , Just fl <- lookupTyConFieldLabel lbl_str tc
|
|
1725 | + -> do
|
|
1726 | + -- GHC does not provide HasField instances for naughty record selectors
|
|
1727 | + -- (see Note [Naughty record selectors] in GHC.Tc.TyCl.Utils),
|
|
1728 | + -- so don't prevent the user from writing such instances.
|
|
1729 | + -- See GHC.Tc.Instance.Class.matchHasField.
|
|
1730 | + -- Test case: T26295.
|
|
1731 | + sel_id <- tcLookupId $ flSelector fl
|
|
1732 | + if isNaughtyRecordSelector sel_id
|
|
1733 | + then return ()
|
|
1734 | + else add_err $ IllegalHasFieldInstanceTyConHasField tc lbl_str
|
|
1723 | 1735 | | otherwise
|
1724 | 1736 | -> return ()
|
1725 | 1737 | Nothing
|
1 | +{-# LANGUAGE GHC2021 #-}
|
|
2 | +{-# LANGUAGE GADTs #-}
|
|
3 | +{-# LANGUAGE DataKinds #-}
|
|
4 | +{-# LANGUAGE OverloadedRecordDot #-}
|
|
5 | +{-# LANGUAGE UndecidableInstances #-}
|
|
6 | +import GHC.Records
|
|
7 | + |
|
8 | +-- large-records mangles record definitions to look like below to
|
|
9 | +-- prevent selector function generation (even implicit ones)
|
|
10 | +data R = forall a b. (a ~ Int, b ~ Char) => MkR
|
|
11 | + { field_a :: a
|
|
12 | + , field_b :: b
|
|
13 | + }
|
|
14 | + |
|
15 | +-- fields in R are naughty, so we can define custom HasField instancs for them
|
|
16 | +instance a ~ Int => HasField "field_a" R a where
|
|
17 | + getField (MkR a _) = a
|
|
18 | + |
|
19 | +ex :: Int
|
|
20 | +ex = r.field_a
|
|
21 | + where
|
|
22 | + r :: R
|
|
23 | + r = MkR 42 'x'
|
|
24 | + |
|
25 | +main :: IO ()
|
|
26 | +main = print ex |
1 | +42 |
... | ... | @@ -20,3 +20,4 @@ test('T12243', normal, compile_and_run, ['']) |
20 | 20 | test('T11228', normal, compile_and_run, [''])
|
21 | 21 | test('T11671_run', normal, compile_and_run, [''])
|
22 | 22 | test('T17551b', [req_th], compile_and_run, [''])
|
23 | +test('T26295', [], compile_and_run, ['']) |