Simon Peyton Jones pushed to branch wip/T26349 at Glasgow Haskell Compiler / GHC

Commits:

3 changed files:

Changes:

  • compiler/GHC/HsToCore/Binds.hs
    ... ... @@ -1602,6 +1602,8 @@ ds_hs_wrapper hs_wrap
    1602 1602
       where
    
    1603 1603
         go WpHole            k = k $ \e -> e
    
    1604 1604
         go (WpSubType w)     k = go (optSubTypeHsWrapper w) k
    
    1605
    +                             -- See (DSST3) in Note [Deep subsumption and WpSubType]
    
    1606
    +                             --             in GHC.Tc.Types.Evidence
    
    1605 1607
         go (WpTyApp ty)      k = k $ \e -> App e (Type ty)
    
    1606 1608
         go (WpEvLam ev)      k = k $ Lam ev
    
    1607 1609
         go (WpTyLam tv)      k = k $ Lam tv
    

  • compiler/GHC/Tc/Errors/Hole.hs
    ... ... @@ -823,9 +823,11 @@ tcFilterHoleFits limit typed_hole ht@(hole_ty, _) candidates =
    823 823
     
    
    824 824
         unfoldWrapper :: HsWrapper -> [Type]
    
    825 825
         unfoldWrapper = reverse . unfWrp'
    
    826
    -      where unfWrp' (WpTyApp ty) = [ty]
    
    827
    -            unfWrp' (WpCompose w1 w2) = unfWrp' w1 ++ unfWrp' w2
    
    828
    -            unfWrp' _ = []
    
    826
    +      where
    
    827
    +        unfWrp' (WpTyApp ty)      = [ty]
    
    828
    +        unfWrp' (WpSubType w)     = unfWrp' w
    
    829
    +        unfWrp' (WpCompose w1 w2) = unfWrp' w1 ++ unfWrp' w2
    
    830
    +        unfWrp' _                  = []
    
    829 831
     
    
    830 832
     
    
    831 833
         -- The real work happens here, where we invoke the type checker using
    

  • compiler/GHC/Tc/Types/Evidence.hs
    ... ... @@ -138,7 +138,7 @@ maybeSymCo NotSwapped co = co
    138 138
     {- Note [Deep subsumption and WpSubType]
    
    139 139
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    140 140
     When making DeepSubsumption checks, we may end up with hard-to-spot identity wrappers.
    
    141
    -For example (#26255) suppose we have
    
    141
    +For example (#26349) suppose we have
    
    142 142
         (forall a. Eq a => a->a) -> Int  <=   (forall a. Eq a => a->a) -> Int
    
    143 143
     The two types are equal so we should certainly get an identity wrapper.  But we'll get
    
    144 144
     tihs wrapper from `tcSubType`:
    
    ... ... @@ -158,11 +158,11 @@ is not sound in general, so we'll end up retaining the lambdas. Two bad results
    158 158
       may not be able to make a decent RULE at all, and will fail with "LHS of rule
    
    159 159
       is too complicated to desugar (#26255)
    
    160 160
     
    
    161
    -It'd be nicest to solve the problem at source, by never generating those
    
    161
    +It'd be ideal to solve the problem at source, by never generating those
    
    162 162
     gruesome wrappers in the first place, but we can't do that because
    
    163 163
     
    
    164
    -* The WpTyLam and WpTyApp are not introduced together in `tcSubType`, so we can't
    
    165
    -  easily cancel them out.   Even if we have
    
    164
    +* The WpTyLam and WpTyApp are introduced independently, not together, in `tcSubType`,
    
    165
    +  so we can't easily cancel them out.   For example, even if we have
    
    166 166
          forall a. t1  <=  forall a. t2
    
    167 167
       there is no guarantee that these are the "same" a.  E.g.
    
    168 168
          forall a b. a -> b -> b   <=   forall x y. y -> x - >x
    
    ... ... @@ -171,17 +171,23 @@ gruesome wrappers in the first place, but we can't do that because
    171 171
     * We have not yet done constraint solving so we don't know what evidence will
    
    172 172
       end up in those WpLet bindings.
    
    173 173
     
    
    174
    -TL;DR we must generate 
    
    175
    -Here's our solution
    
    174
    +TL;DR we must generate the wrapper and then optimise it way if it turns out
    
    175
    +that it is a no-op.  Here's our solution
    
    176 176
     
    
    177 177
     (DSST1) Tag the wrappers generated from a subtype check with WpSubType. In normal
    
    178 178
       wrappers the binders of a WpTyLam or WpEvLam can scope over the "hole" of the
    
    179 179
       wrapper -- that is how we introduce type-lambdas and dictionary-lambda into the
    
    180 180
       terms!  But in /subtype/ wrappers, these type/dictionary lambdas only scope over
    
    181
    -  the WpTyApp and WpEvApp nodes in the /same/ wrapper.  That is w
    
    181
    +  the WpTyApp and WpEvApp nodes in the /same/ wrapper.  That is what justifies us
    
    182
    +  eta-reducing the type/dictionarly lambdas.
    
    182 183
     
    
    183
    -(WpSubType wp) means the same as `wp`, but with the added promise that
    
    184
    -the binders in `wp` do not scope over the hole
    
    184
    +  In short, (WpSubType wp) means the same as `wp`, but with the added promise that
    
    185
    +  the binders in `wp` do not scope over the hole
    
    186
    +
    
    187
    +(DSST2) Avoid creating a WpSubType in the common WpHole case, using `mkWpSubType`.
    
    188
    +
    
    189
    +(DSST3) When desugaring, try eta-reduction on the payload of a WpSubType.
    
    190
    +  This is done in `GHC.HsToCore.Binds.dsHsWrapper` by the call to `optSubTypeHsWrapper`.
    
    185 191
     -}
    
    186 192
     
    
    187 193
     -- We write    wrap :: t1 ~> t2
    
    ... ... @@ -190,7 +196,7 @@ data HsWrapper
    190 196
       = WpHole                      -- The identity coercion
    
    191 197
     
    
    192 198
       | WpSubType HsWrapper   -- (WpSubType wp) Means the same as `wp`
    
    193
    -                          -- But see Note [WpSubType]
    
    199
    +                          -- See Note [Deep subsumption and WpSubType] (DSST1)
    
    194 200
     
    
    195 201
       | WpCompose HsWrapper HsWrapper
    
    196 202
            -- (wrap1 `WpCompose` wrap2)[e] = wrap1[ wrap2[ e ]]
    
    ... ... @@ -299,6 +305,7 @@ mkWpFun w_arg w_res t1 t2 = WpFun w_arg w_res t1 t2
    299 305
       -- [Wrinkle: Typed Template Haskell] in Note [hasFixedRuntimeRep] in GHC.Tc.Utils.Concrete.
    
    300 306
     
    
    301 307
     mkWpSubType :: HsWrapper -> HsWrapper
    
    308
    +-- See (DSST2) in Note [Deep subsumption and WpSubType]
    
    302 309
     mkWpSubType WpHole      = WpHole
    
    303 310
     mkWpSubType (WpCast co) = WpCast co
    
    304 311
     mkWpSubType w           = WpSubType w
    
    ... ... @@ -393,7 +400,7 @@ hsWrapDictBinders wrap = go wrap
    393 400
        go (w1 `WpCompose` w2) = go w1 `unionBags` go w2
    
    394 401
        go (WpFun _ w _ _)     = go w
    
    395 402
        go WpHole              = emptyBag
    
    396
    -   go (WpSubType {})      = emptyBag  -- See Note [WpSubType]
    
    403
    +   go (WpSubType {})      = emptyBag  -- See Note [Deep subsumption and WpSubType]
    
    397 404
        go (WpCast  {})        = emptyBag
    
    398 405
        go (WpEvApp {})        = emptyBag
    
    399 406
        go (WpTyLam {})        = emptyBag
    
    ... ... @@ -420,9 +427,11 @@ collectHsWrapBinders wrap = go wrap []
    420 427
     
    
    421 428
     
    
    422 429
     optSubTypeHsWrapper :: HsWrapper -> HsWrapper
    
    430
    +-- This optimiser is used only on the payload of WpSubType
    
    431
    +-- It finds cases where the entire wrapper is a no-op
    
    432
    +-- See (DSST3) in Note [Deep subsumption and WpSubType]
    
    423 433
     optSubTypeHsWrapper wrap
    
    424
    -  = -- pprTrace "optHsWrapper" (vcat [ text "in:" <+> ppr wrap, text "out:" <+> ppr (opt wrap) ]) $
    
    425
    -    opt wrap
    
    434
    +  = opt wrap
    
    426 435
       where
    
    427 436
         opt :: HsWrapper -> HsWrapper
    
    428 437
         opt w = foldr (<.>) WpHole (opt1 w [])
    
    ... ... @@ -436,18 +445,17 @@ optSubTypeHsWrapper wrap
    436 445
         opt1 (WpCast co)            ws = opt_co co ws
    
    437 446
         opt1 (WpEvLam ev)           ws = opt_ev_lam ev ws
    
    438 447
         opt1 (WpTyLam tv)           ws = opt_ty_lam tv ws
    
    439
    -    opt1 (WpLet binds)          ws = opt_let binds ws
    
    448
    +    opt1 (WpLet binds)          ws = pushWpLet binds ws
    
    440 449
         opt1 (WpFun w1 w2 sty1 ty2) ws = mk_wp_fun (opt w1) (opt w2) sty1 ty2 ws
    
    441 450
         opt1 w@(WpTyApp {})         ws = w : ws
    
    442 451
         opt1 w@(WpEvApp {})         ws = w : ws
    
    443 452
     
    
    444
    -    ------------------
    
    445
    -    opt_let b@(EvBinds bs) ws | isEmptyBag bs = ws
    
    446
    -                              | otherwise     = WpLet b : ws
    
    447
    -    opt_let (TcEvBinds {}) _  = pprPanic "optHsWrapper1" (ppr wrap)
    
    448
    -
    
    449 453
         -----------------
    
    450 454
         -- (WpTyLam a <+> WpTyApp a <+> w) = w
    
    455
    +    -- i.e.   /\a. <hole> a   -->  <hole>
    
    456
    +    -- This is only valid if whatever fills the hole does not mention 'a'
    
    457
    +    -- But that's guaranteed in subtype-wrappers;
    
    458
    +    -- see (DSST1) in Note [Deep subsumption and WpSubType]
    
    451 459
         opt_ty_lam tv (WpTyApp ty : ws)
    
    452 460
           | Just tv' <- getTyVar_maybe ty
    
    453 461
           , tv==tv'
    
    ... ... @@ -458,15 +466,12 @@ optSubTypeHsWrapper wrap
    458 466
         opt_ty_lam tv (WpCast co : ws)
    
    459 467
           = opt_co (mkHomoForAllCo tv co) (opt_ty_lam tv ws)
    
    460 468
     
    
    461
    -    opt_ty_lam tv (WpLet bs : ws)
    
    462
    -      | Just ws' <- pushWpLet bs ws
    
    463
    -      = opt_ty_lam tv ws'
    
    464
    -
    
    465 469
         opt_ty_lam tv ws
    
    466 470
           = WpTyLam tv : ws
    
    467 471
     
    
    468 472
         -----------------
    
    469 473
         -- (WpEvLam ev <+> WpEvAp ev <+> w) = w
    
    474
    +    -- Similar notes to WpTyLam
    
    470 475
         opt_ev_lam ev (WpEvApp ev_tm : ws)
    
    471 476
           | EvExpr (Var ev') <- ev_tm
    
    472 477
           , ev == ev'
    
    ... ... @@ -481,9 +486,6 @@ optSubTypeHsWrapper wrap
    481 486
                             (mkNomReflCo ManyTy)
    
    482 487
                             (mkRepReflCo (idType ev))
    
    483 488
                             co
    
    484
    -    opt_ev_lam ev (WpLet bs : ws)
    
    485
    -      | Just ws' <- pushWpLet bs ws
    
    486
    -      = opt_ev_lam ev ws'
    
    487 489
     
    
    488 490
         opt_ev_lam ev ws
    
    489 491
           = WpEvLam ev : ws
    
    ... ... @@ -505,48 +507,64 @@ optSubTypeHsWrapper wrap
    505 507
           where
    
    506 508
             co_ify co1 co2 = opt_co (mk_wp_fun_co w co1 co2) ws
    
    507 509
     
    
    508
    -pushWpLet :: TcEvBinds -> [HsWrapper] -> Maybe [HsWrapper]
    
    510
    +pushWpLet :: TcEvBinds -> [HsWrapper] -> [HsWrapper]
    
    511
    +-- See if we can transform
    
    512
    +--    WpLet binds <.> w1 <.> .. <.> wn   -->   w1' <.> .. <.> wn'
    
    513
    +-- by substitution.
    
    514
    +-- We do this just for the narrow case when
    
    515
    +--   - the `binds` are all just v=w, variables only
    
    516
    +--   - the wi are all WpTyApp, WpEvApp, or WpCast
    
    517
    +-- This is just enough to get us the eta-reductions that we seek
    
    509 518
     pushWpLet tc_ev_binds ws
    
    510
    -  | EvBinds binds <- tc_ev_binds
    
    511
    -  , Just env <- evBindIdSwizzle binds
    
    512
    -  = go env ws
    
    513
    -  | otherwise
    
    514
    -  = Nothing
    
    519
    +  = case tc_ev_binds of
    
    520
    +      TcEvBinds {} -> pprPanic "pushWpLet" (ppr tc_ev_binds)
    
    521
    +      EvBinds binds
    
    522
    +        | isEmptyBag binds
    
    523
    +        -> ws
    
    524
    +        | Just env <- ev_bind_swizzle binds
    
    525
    +        -> case go env ws of
    
    526
    +              Just ws' -> ws'
    
    527
    +              Nothing  -> bale_out
    
    528
    +        | otherwise
    
    529
    +        -> bale_out
    
    515 530
       where
    
    531
    +    bale_out = WpLet tc_ev_binds : ws
    
    532
    +
    
    516 533
         go :: IdEnv Id -> [HsWrapper] -> Maybe [HsWrapper]
    
    517 534
         go env (WpCast co  : ws) = do { ws' <- go env ws
    
    518 535
                                       ; return (WpCast co  : ws') }
    
    519 536
         go env (WpTyApp ty : ws) = do { ws' <- go env ws
    
    520 537
                                       ; return (WpTyApp ty : ws') }
    
    521 538
         go env (WpEvApp (EvExpr (Var v)) : ws)
    
    522
    -       = do { v'  <- swizzleId env v
    
    539
    +       = do { v'  <- swizzle_id env v
    
    523 540
                 ; ws' <- go env ws
    
    524 541
                 ; return (WpEvApp (EvExpr (Var v')) : ws') }
    
    525 542
     
    
    526 543
         go _ ws = case ws of
    
    527 544
                      []    -> Just []
    
    528
    -                 (_:_) -> Nothing  -- Could not fully eliminate it
    
    545
    +                 (_:_) -> Nothing  -- Could not fully eliminate the WpLet
    
    529 546
     
    
    530
    -swizzleId :: IdEnv Id -> Id -> Maybe Id
    
    531
    --- Nothing <=> ran out of fuel
    
    532
    --- Shoul
    
    533
    -swizzleId env v = go 100 v
    
    534
    -  where
    
    535
    -    go :: Int -> EvId -> Maybe EvId
    
    536
    -    go fuel v
    
    537
    -      | fuel == 0                     = Nothing
    
    538
    -      | Just v' <- lookupVarEnv env v = go (fuel-1) v'
    
    539
    -      | otherwise                     = Just v
    
    540
    -
    
    541
    -evBindIdSwizzle :: Bag EvBind -> Maybe (IdEnv Id)
    
    542
    -evBindIdSwizzle evbs = foldl' do_one (Just emptyVarEnv) evbs
    
    543
    -  where
    
    544
    -    do_one :: Maybe (IdEnv Id) -> EvBind -> Maybe (IdEnv Id)
    
    545
    -    do_one Nothing _ = Nothing
    
    546
    -    do_one (Just swizzle) (EvBind {eb_lhs = bndr, eb_rhs = rhs})
    
    547
    -      = case rhs of
    
    548
    -           EvExpr (Var v) -> Just (extendVarEnv swizzle bndr v)
    
    549
    -           _              -> Nothing
    
    547
    +    swizzle_id :: IdEnv Id -> Id -> Maybe Id
    
    548
    +    -- Nothing <=> ran out of fuel
    
    549
    +    -- This is just belt and braces; we should never build bottom evidence
    
    550
    +    swizzle_id env v = go 100 v
    
    551
    +      where
    
    552
    +        go :: Int -> EvId -> Maybe EvId
    
    553
    +        go fuel v
    
    554
    +          | fuel == 0                     = Nothing
    
    555
    +          | Just v' <- lookupVarEnv env v = go (fuel-1) v'
    
    556
    +          | otherwise                     = Just v
    
    557
    +
    
    558
    +    ev_bind_swizzle :: Bag EvBind -> Maybe (IdEnv Id)
    
    559
    +    -- Succeeds only if the bindings are all var-to-var bindings
    
    560
    +    ev_bind_swizzle evbs = foldl' do_one (Just emptyVarEnv) evbs
    
    561
    +      where
    
    562
    +        do_one :: Maybe (IdEnv Id) -> EvBind -> Maybe (IdEnv Id)
    
    563
    +        do_one Nothing _ = Nothing
    
    564
    +        do_one (Just swizzle) (EvBind {eb_lhs = bndr, eb_rhs = rhs})
    
    565
    +          = case rhs of
    
    566
    +               EvExpr (Var v) -> Just (extendVarEnv swizzle bndr v)
    
    567
    +               _              -> Nothing
    
    550 568
     
    
    551 569
     {-
    
    552 570
     ************************************************************************