Oleg Grenrus pushed to branch wip/T26295 at Glasgow Haskell Compiler / GHC

Commits:

4 changed files:

Changes:

  • compiler/GHC/Tc/Validity.hs
    ... ... @@ -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
    

  • testsuite/tests/overloadedrecflds/should_run/T26295.hs
    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

  • testsuite/tests/overloadedrecflds/should_run/T26295.stdout
    1
    +42

  • testsuite/tests/overloadedrecflds/should_run/all.T
    ... ... @@ -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, [''])