Florian Ragwitz pushed to branch wip/rafl/cover-data at Glasgow Haskell Compiler / GHC

Commits:

3 changed files:

Changes:

  • compiler/GHC/HsToCore/Ticks.hs
    ... ... @@ -251,7 +251,7 @@ addTickLHsBind (L pos (XHsBindsLR bind@(AbsBinds { abs_binds = binds
    251 251
     
    
    252 252
        add_rec_sels env =
    
    253 253
          env{ recSelBinds = recSelBinds env `extendVarEnvList`
    
    254
    -                          [ (abe_mono, abe_poly)
    
    254
    +                          [ (abe_mono, [abe_poly])
    
    255 255
                               | ABE{ abe_poly, abe_mono } <- abs_exports
    
    256 256
                               , RecSelId{} <- [idDetails abe_poly] ] }
    
    257 257
     
    
    ... ... @@ -270,8 +270,8 @@ addTickLHsBind (L pos (funBind@(FunBind { fun_id = L _ id, fun_matches = matches
    270 270
       case tickish of { ProfNotes | inline -> return (L pos funBind); _ -> do
    
    271 271
     
    
    272 272
       -- See Note [Record-selector ticks]
    
    273
    -  selTick <- recSelTick id
    
    274
    -  case selTick of { Just tick -> tick_rec_sel tick; _ -> do
    
    273
    +  selTicks <- recSelTick id
    
    274
    +  case selTicks of { Just ticks -> tick_rec_sel ticks; _ -> do
    
    275 275
     
    
    276 276
       (fvs, mg) <-
    
    277 277
             getFreeVars $
    
    ... ... @@ -303,8 +303,8 @@ addTickLHsBind (L pos (funBind@(FunBind { fun_id = L _ id, fun_matches = matches
    303 303
       } }
    
    304 304
       where
    
    305 305
         -- See Note [Record-selector ticks]
    
    306
    -    tick_rec_sel tick =
    
    307
    -      pure $ L pos $ funBind { fun_ext = second (tick :) (fun_ext funBind) }
    
    306
    +    tick_rec_sel ticks =
    
    307
    +      pure $ L pos $ funBind { fun_ext = second (ticks ++) (fun_ext funBind) }
    
    308 308
     
    
    309 309
     
    
    310 310
     -- Note [Record-selector ticks]
    
    ... ... @@ -319,9 +319,8 @@ addTickLHsBind (L pos (funBind@(FunBind { fun_id = L _ id, fun_matches = matches
    319 319
     -- coverage purposes to improve the developer experience.
    
    320 320
     --
    
    321 321
     -- This is done by keeping track of which 'Id's are effectively bound to
    
    322
    --- record fields (using NamedFieldPuns or RecordWildCards) in 'TickTransEnv's
    
    323
    --- 'recSelBinds', and making 'HsVar's corresponding to those fields tick the
    
    324
    --- appropriate box when executed.
    
    322
    +-- record fields in 'TickTransEnv's 'recSelBinds', and making 'HsVar's
    
    323
    +-- corresponding to those fields tick the appropriate box when executed.
    
    325 324
     --
    
    326 325
     -- To enable that, we also treat 'FunBind's for record selector functions
    
    327 326
     -- specially. We only create a TopLevelBox for the record selector function,
    
    ... ... @@ -330,10 +329,7 @@ addTickLHsBind (L pos (funBind@(FunBind { fun_id = L _ id, fun_matches = matches
    330 329
     -- the fun_matches match group for record selector functions.
    
    331 330
     --
    
    332 331
     -- This scheme could be extended further in the future, making coverage for
    
    333
    --- constructor fields (named or even positional) mean that the field was
    
    334
    --- accessed at run-time. For the time being, we only cover NamedFieldPuns and
    
    335
    --- RecordWildCards binds to cover most practical use-cases while keeping it
    
    336
    --- simple.
    
    332
    +-- positional constructor fields mean that the field was accessed at run-time.
    
    337 333
     
    
    338 334
     -- TODO: Revisit this
    
    339 335
     addTickLHsBind (L pos (pat@(PatBind { pat_lhs = lhs
    
    ... ... @@ -519,7 +515,7 @@ addTickHsExpr :: HsExpr GhcTc -> TM (HsExpr GhcTc)
    519 515
     -- See Note [Record-selector ticks]
    
    520 516
     addTickHsExpr e@(HsVar _ (L _ id)) =
    
    521 517
         freeVar id >> recSelTick id >>= pure . maybe e wrap
    
    522
    -  where wrap tick = XExpr . HsTick tick . noLocA $ e
    
    518
    +  where wrap = foldr (\tick -> XExpr . HsTick tick . noLocA) e
    
    523 519
     addTickHsExpr e@(HsIPVar {})            = return e
    
    524 520
     addTickHsExpr e@(HsOverLit {})          = return e
    
    525 521
     addTickHsExpr e@(HsOverLabel{})         = return e
    
    ... ... @@ -1086,7 +1082,7 @@ data TickTransEnv = TTE { fileName :: FastString
    1086 1082
                             , blackList    :: Set RealSrcSpan
    
    1087 1083
                             , this_mod     :: Module
    
    1088 1084
                             , tickishType  :: TickishType
    
    1089
    -                        , recSelBinds  :: IdEnv Id
    
    1085
    +                        , recSelBinds  :: IdEnv [Id]
    
    1090 1086
                             }
    
    1091 1087
     
    
    1092 1088
     --      deriving Show
    
    ... ... @@ -1241,11 +1237,12 @@ allocTickBox boxLabel countEntries topOnly pos m
    1241 1237
           tickish <- mkTickish boxLabel countEntries topOnly pos fvs (declPath env)
    
    1242 1238
           return (this_loc (XExpr $ HsTick tickish $ this_loc e))
    
    1243 1239
     
    
    1244
    -recSelTick :: Id -> TM (Maybe CoreTickish)
    
    1240
    +recSelTick :: Id -> TM (Maybe [CoreTickish])
    
    1245 1241
     recSelTick id = ifDensity TickForCoverage maybe_tick (pure Nothing)
    
    1246 1242
       where
    
    1247 1243
         maybe_tick = getEnv >>=
    
    1248
    -      maybe (pure Nothing) tick . (`lookupVarEnv` id) . recSelBinds
    
    1244
    +      maybe (pure Nothing) tick_all . (`lookupVarEnv` id) . recSelBinds
    
    1245
    +    tick_all = fmap (Just . catMaybes) . mapM tick
    
    1249 1246
         tick sel = getState >>=
    
    1250 1247
           maybe (alloc sel) (pure . Just) . (`lookupVarEnv` sel) . recSelTicks
    
    1251 1248
         alloc sel = allocATickBox (box sel) False False (getSrcSpan sel) noFVs
    
    ... ... @@ -1367,7 +1364,7 @@ class CollectBinders a where
    1367 1364
     --
    
    1368 1365
     -- See Note [Record-selector ticks].
    
    1369 1366
     class CollectFldBinders a where
    
    1370
    -  collectFldBinds :: a -> IdEnv Id
    
    1367
    +  collectFldBinds :: a -> IdEnv [Id]
    
    1371 1368
     
    
    1372 1369
     instance CollectBinders (LocatedA (Pat GhcTc)) where
    
    1373 1370
       collectBinds = collectPatBinders CollNoDictBinders
    
    ... ... @@ -1385,41 +1382,39 @@ instance (CollectFldBinders a) => CollectFldBinders [a] where
    1385 1382
     instance (CollectFldBinders e) => CollectFldBinders (GenLocated l e) where
    
    1386 1383
       collectFldBinds = collectFldBinds . unLoc
    
    1387 1384
     instance CollectFldBinders (Pat GhcTc) where
    
    1388
    -  collectFldBinds ConPat{ pat_args = RecCon HsRecFields{ rec_flds, rec_dotdot } } =
    
    1389
    -    collectFldBinds rec_flds `plusVarEnv` plusVarEnvList (zipWith fld_bnds [0..] rec_flds)
    
    1390
    -    where n_explicit | Just (L _ (RecFieldsDotDot n)) <- rec_dotdot = n
    
    1391
    -                     | otherwise = length rec_flds
    
    1392
    -          fld_bnds n (L _ HsFieldBind{ hfbLHS = L _ FieldOcc{ foLabel = L _ sel }
    
    1393
    -                                     , hfbRHS = L _ (VarPat _ (L _ var))
    
    1394
    -                                     , hfbPun })
    
    1395
    -            | hfbPun || n >= n_explicit = unitVarEnv var sel
    
    1396
    -          fld_bnds _ _ = emptyVarEnv
    
    1397
    -  collectFldBinds ConPat{ pat_args = PrefixCon pats } = collectFldBinds pats
    
    1398
    -  collectFldBinds ConPat{ pat_args = InfixCon p1 p2 } = collectFldBinds [p1, p2]
    
    1399
    -  collectFldBinds (LazyPat _ pat) = collectFldBinds pat
    
    1400
    -  collectFldBinds (BangPat _ pat) = collectFldBinds pat
    
    1401
    -  collectFldBinds (AsPat _ _ pat) = collectFldBinds pat
    
    1402
    -  collectFldBinds (ViewPat _ _ pat) = collectFldBinds pat
    
    1403
    -  collectFldBinds (ParPat _ pat) = collectFldBinds pat
    
    1404
    -  collectFldBinds (ListPat _ pats) = collectFldBinds pats
    
    1405
    -  collectFldBinds (TuplePat _ pats _) = collectFldBinds pats
    
    1406
    -  collectFldBinds (SumPat _ pats _ _) = collectFldBinds pats
    
    1407
    -  collectFldBinds (SigPat _ pat _) = collectFldBinds pat
    
    1408
    -  collectFldBinds (XPat exp) = collectFldBinds exp
    
    1409
    -  collectFldBinds VarPat{} = emptyVarEnv
    
    1410
    -  collectFldBinds WildPat{} = emptyVarEnv
    
    1411
    -  collectFldBinds OrPat{} = emptyVarEnv
    
    1412
    -  collectFldBinds LitPat{} = emptyVarEnv
    
    1413
    -  collectFldBinds NPat{} = emptyVarEnv
    
    1414
    -  collectFldBinds NPlusKPat{} = emptyVarEnv
    
    1415
    -  collectFldBinds SplicePat{} = emptyVarEnv
    
    1416
    -  collectFldBinds EmbTyPat{} = emptyVarEnv
    
    1417
    -  collectFldBinds InvisPat{} = emptyVarEnv
    
    1385
    +  collectFldBinds = go [] where
    
    1386
    +    go path ConPat{ pat_args = RecCon HsRecFields{ rec_flds } } =
    
    1387
    +      plusVarEnvList (map fld_binds rec_flds)
    
    1388
    +        where fld_binds (L _ HsFieldBind{ hfbLHS = L _ FieldOcc{ foLabel = L _ sel }
    
    1389
    +                                        , hfbRHS = L _ rhs })
    
    1390
    +                = go (sel:path) rhs
    
    1391
    +    go path ConPat{ pat_args = PrefixCon ps } =
    
    1392
    +      plusVarEnvList (map (go path . unLoc) ps)
    
    1393
    +    go path ConPat{ pat_args = InfixCon (L _ p1) (L _ p2) } =
    
    1394
    +      go path p1 `plusVarEnv` go path p2
    
    1395
    +    go [] VarPat{} = emptyVarEnv
    
    1396
    +    go path (VarPat _ (L _ var)) = unitVarEnv var path
    
    1397
    +    go path (LazyPat _ (L _ p)) = go path p
    
    1398
    +    go path (BangPat _ (L _ p)) = go path p
    
    1399
    +    go path (AsPat _ _ (L _ p)) = go path p
    
    1400
    +    go path (ViewPat _ _ (L _ p)) = go path p
    
    1401
    +    go path (ParPat _ (L _ p)) = go path p
    
    1402
    +    go path (SigPat _ (L _ p) _) = go path p
    
    1403
    +    go path (SumPat _ (L _ p) _ _)  = go path p
    
    1404
    +    go path (XPat (CoPat _ p _)) = go path p
    
    1405
    +    go path (XPat (ExpansionPat _ p)) = go path p
    
    1406
    +    go path (ListPat _ ps) = plusVarEnvList (map (go path . unLoc) ps)
    
    1407
    +    go path (TuplePat _ ps _) = plusVarEnvList (map (go path . unLoc) ps)
    
    1408
    +    go _ WildPat{} = emptyVarEnv
    
    1409
    +    go _ OrPat{} = emptyVarEnv
    
    1410
    +    go _ LitPat{} = emptyVarEnv
    
    1411
    +    go _ NPat{} = emptyVarEnv
    
    1412
    +    go _ NPlusKPat{} = emptyVarEnv
    
    1413
    +    go _ SplicePat{} = emptyVarEnv
    
    1414
    +    go _ EmbTyPat{} = emptyVarEnv
    
    1415
    +    go _ InvisPat{} = emptyVarEnv
    
    1418 1416
     instance (CollectFldBinders r) => CollectFldBinders (HsFieldBind l r) where
    
    1419 1417
       collectFldBinds = collectFldBinds . hfbRHS
    
    1420
    -instance CollectFldBinders XXPatGhcTc where
    
    1421
    -  collectFldBinds (CoPat _ pat _) = collectFldBinds pat
    
    1422
    -  collectFldBinds (ExpansionPat _ pat) = collectFldBinds pat
    
    1423 1418
     instance CollectFldBinders (HsLocalBinds GhcTc) where
    
    1424 1419
       collectFldBinds (HsValBinds _ bnds) = collectFldBinds bnds
    
    1425 1420
       collectFldBinds HsIPBinds{} = emptyVarEnv
    
    ... ... @@ -1430,9 +1425,9 @@ instance CollectFldBinders (HsValBinds GhcTc) where
    1430 1425
     instance CollectFldBinders (HsBind GhcTc) where
    
    1431 1426
       collectFldBinds PatBind{ pat_lhs } = collectFldBinds pat_lhs
    
    1432 1427
       collectFldBinds (XHsBindsLR AbsBinds{ abs_exports, abs_binds }) =
    
    1433
    -    mkVarEnv [ (abe_poly, sel)
    
    1428
    +    mkVarEnv [ (abe_poly, sels)
    
    1434 1429
                  | ABE{ abe_poly, abe_mono } <- abs_exports
    
    1435
    -             , Just sel <- [lookupVarEnv monos abe_mono] ]
    
    1430
    +             , Just sels <- [lookupVarEnv monos abe_mono] ]
    
    1436 1431
         where monos = collectFldBinds abs_binds
    
    1437 1432
       collectFldBinds VarBind{} = emptyVarEnv
    
    1438 1433
       collectFldBinds FunBind{} = emptyVarEnv
    

  • testsuite/tests/hpc/recsel/recsel.hs
    ... ... @@ -10,7 +10,8 @@ import Trace.Hpc.Tix
    10 10
     import Trace.Hpc.Reflect
    
    11 11
     
    
    12 12
     data Foo = Foo { fooA, fooB, fooC, fooD, fooE, fooF, fooG, fooH, fooI
    
    13
    -               , fooJ, fooK, fooL, fooM, fooN, fooO :: Int }
    
    13
    +               , fooJ, fooK, fooL, fooM, fooN, fooO :: Int
    
    14
    +               , fooP :: Maybe Int }
    
    14 15
     data Bar = Bar { barFoo :: Foo }
    
    15 16
     
    
    16 17
     fAB Foo{..} = fooA + fooB
    
    ... ... @@ -35,14 +36,16 @@ fL = runIdentity . runKleisli (proc f -> do
    35 36
     fM f | Foo{..} <- f = fooM
    
    36 37
     fN f = fooN f
    
    37 38
     fO = runIdentity . runKleisli (proc Foo{..} -> returnA -< fooO)
    
    39
    +fP Foo{fooP = Just x} = x
    
    40
    +fP _ = 0
    
    38 41
     
    
    39 42
     recSel (n, TopLevelBox [s]) | any (`isPrefixOf` s) ["foo", "bar"] = Just (n, s)
    
    40 43
     recSel _ = Nothing
    
    41 44
     
    
    42 45
     main = do
    
    43
    -  let foo = Foo 42 23 0 1 2 3 4 5 6 7 0xaffe 9 10 11 12
    
    46
    +  let foo = Foo 42 23 0 1 2 3 4 5 6 7 0xaffe 9 10 11 12 (Just 13)
    
    44 47
       mapM_ (print . ($ foo))
    
    45
    -        [fAB, fC, fD False, fE . Bar, fF, fG, fH, fI, fJ, fK, fL, fM, fN, fO]
    
    48
    +        [fAB, fC, fD False, fE . Bar, fF, fG, fH, fI, fJ, fK, fL, fM, fN, fO, fP]
    
    46 49
       (Mix _ _ _ _ mixs) <- readMix [".hpc"] (Left "Main")
    
    47 50
       let sels = mapMaybe recSel . zip [0..] $ map snd mixs
    
    48 51
       (Tix [TixModule "Main" _ _ tix]) <- examineTix
    

  • testsuite/tests/hpc/recsel/recsel.stdout
    ... ... @@ -12,13 +12,14 @@
    12 12
     10
    
    13 13
     11
    
    14 14
     12
    
    15
    -(0,"barFoo")
    
    15
    +13
    
    16
    +(1,"barFoo")
    
    16 17
     (1,"fooA")
    
    17 18
     (1,"fooB")
    
    18 19
     (1,"fooC")
    
    19 20
     (0,"fooD")
    
    20 21
     (1,"fooE")
    
    21
    -(0,"fooF")
    
    22
    +(1,"fooF")
    
    22 23
     (1,"fooG")
    
    23 24
     (1,"fooH")
    
    24 25
     (1,"fooI")
    
    ... ... @@ -28,3 +29,4 @@
    28 29
     (1,"fooM")
    
    29 30
     (1,"fooN")
    
    30 31
     (1,"fooO")
    
    32
    +(1,"fooP")