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

Commits:

6 changed files:

Changes:

  • compiler/GHC/Core.hs
    ... ... @@ -465,8 +465,8 @@ TL;DR: we relaxed the let/app invariant to become the let-can-float invariant.
    465 465
     
    
    466 466
     Note [Type and coercion lets]
    
    467 467
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    468
    -We allow
    
    469
    -   let @a = TYPE ty in ...
    
    468
    +We allow non-recursive type lets:
    
    469
    +   let a = TYPE ty in ...
    
    470 470
     and similarly for coercions.
    
    471 471
     
    
    472 472
        TODO: fill this out
    
    ... ... @@ -475,7 +475,7 @@ Wrinkles:
    475 475
     
    
    476 476
     (TCL1) In a type let (Let @a = TYPE ty in body), we do /not/ insist that
    
    477 477
       the binder `a` has a TyVarUnfolding.  But if it does not, then `body`
    
    478
    -  must be well-typed without paying atention to the binding. More precisely,
    
    478
    +  must be well-typed without paying attention to the binding. More precisely,
    
    479 479
            let @a = TYPE ty in body
    
    480 480
       where `a` has no TyVarUnfolding, is well-typed iff
    
    481 481
            (/\a. body) ty
    
    ... ... @@ -489,15 +489,32 @@ Wrinkles:
    489 489
       (which is always substituted) with the tyvar-replete-with-unfolding, rather
    
    490 490
       than merely extending the in-scope set as we do for Ids.
    
    491 491
     
    
    492
    +(TCL3) In the output of the desugarer it is very convenient to allow
    
    493
    +      let a = <type> in ...a....
    
    494
    +  where the occurrences of `a` do /not/ have an unfolding, but yet it is essential
    
    495
    +  to substitute <type> for `a` when Linting.  Why?  When compiling nested pattern
    
    496
    +  matching we may combine patterns
    
    497
    +      K @a1 (co1 :: a1 ~ T) pat1 -> e1
    
    498
    +      K @a2 (co2 :: a2 ~ T) pat2 -> e2
    
    499
    +  to get a single, shared pattern, something like
    
    500
    +      K @a1 (co1 :: a1 ~ T) x -> let { a2 = a1; co2 = co1 } in
    
    501
    +                                 case x of
    
    502
    +                                   pat1 -> e1
    
    503
    +                                   pat2 -> e2
    
    504
    +  The bindings { a2=a1; co2=co1 } just make the binders in the two patterns line
    
    505
    +  up.  But for this to be Lint-correct we must actually substitute `a1` for `a2`.
    
    506
    +
    
    507
    +  So, in the ouptut of the desugarer only, if there is no unfolding on the binder,
    
    508
    +  we just extend the subustitution.
    
    509
    +
    
    510
    +  It's a bit of a hack, but the first roun dof simplification esablishes (TCL1) or
    
    511
    +  (TCL2).
    
    512
    +
    
    492 513
     So: (TCL1) + (TCL2) =
    
    493 514
       EITHER `a` has an unfolding at its binding site,
    
    494 515
          and that unfolding is replicated at every occurrence site
    
    495 516
       OR it doesn't and the occurrences don't either.
    
    496 517
     
    
    497
    -
    
    498
    -OR we could insist that tyvar bindings always have an unfolding, and use
    
    499
    -a beta-redex if not.
    
    500
    -
    
    501 518
     Note [Core top-level string literals]
    
    502 519
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    503 520
     As an exception to the usual rule that top-level binders must be lifted,
    

  • compiler/GHC/Core/Lint.hs
    ... ... @@ -235,8 +235,6 @@ in GHC.Core.Opt.WorkWrap.Utils. (Maybe there are other "clients" of this featur
    235 235
       for this purpose -- it contains only TyCoVars.  Instead we have a separate
    
    236 236
       le_ids for the in-scope Id binders.
    
    237 237
     
    
    238
    -Sigh.  We might want to explore getting rid of type-let!
    
    239
    -
    
    240 238
     Note [Bad unsafe coercion]
    
    241 239
     ~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    242 240
     For discussion see https://gitlab.haskell.org/ghc/ghc/wikis/bad-unsafe-coercions
    
    ... ... @@ -570,23 +568,31 @@ lintLetExpr :: TyVarSet -- Enclosing let-bound tyvars, all with unfoldings
    570 568
     lintLetExpr tvs (Let (NonRec tv (Type rhs_ty)) body)
    
    571 569
       | isTyVar tv
    
    572 570
       =     -- See Note [Linting type lets]
    
    573
    -    do  { case tyVarUnfolding_maybe tv of
    
    574
    -             Nothing     -> return () -- See GHC.Core Note [Type and coercion lets] wrinkle (TCL1)
    
    575
    -             Just unf_ty -> -- These comparisons compare InTypes, which is fine
    
    576
    -                            do { ensureEqTys (tyVarKind tv) (typeKind rhs_ty) $
    
    577
    -                                 tv_err unf_ty "Let-bound tyvar kind incompatible with RHS:"
    
    578
    -                               ; ensureEqTys unf_ty rhs_ty $
    
    579
    -                                 tv_err unf_ty "Let-bound tyvar unfolding not same as RHS:" }
    
    580
    -
    
    581
    -        ; addLoc (RhsOf tv) $ lintType rhs_ty
    
    582
    -
    
    583
    -        ; lintTyCoBndr tv     $ \ tv' ->
    
    584
    -          addLoc (BodyOfLet tv) $
    
    585
    -          lintLetExpr (tvs `extendVarSet` tv') body }
    
    571
    +    do { -- Lint the RHS type
    
    572
    +         rhs_ty' <- addLoc (RhsOf tv) $ lintTypeAndSubst rhs_ty
    
    573
    +
    
    574
    +       ; lintTyCoBndr tv $ \ tv' ->
    
    575
    +    do { -- Check that the RHS has the same kind as the tyvar
    
    576
    +          addLoc (RhsOf tv) $
    
    577
    +          lintTyKind tv' rhs_ty'
    
    578
    +
    
    579
    +        -- Check the unfolding
    
    580
    +        -- See GHC.Core Note [Type and coercion lets] wrinkle (TCL1)
    
    581
    +        ; case tyVarUnfolding_maybe tv' of
    
    582
    +             Nothing      -> return ()
    
    583
    +             Just unf_ty' -> ensureEqTys unf_ty' rhs_ty' $
    
    584
    +                             tv_err tv' unf_ty' rhs_ty'
    
    585
    +
    
    586
    +          -- Check the body
    
    587
    +        ; extendTvLetSubst tv rhs_ty' $
    
    588
    +          addLoc (BodyOfLet tv)     $
    
    589
    +          lintLetExpr (tvs `extendVarSet` tv') body
    
    590
    +     } }
    
    586 591
       where
    
    587
    -    tv_err unf_ty msg = hang (text msg  <+> pprTyVarWithKind tv)
    
    588
    -                           2 (vcat [ text "Unfolding:" <+> ppr unf_ty
    
    589
    -                                   , text "RHS:      " <+> ppr rhs_ty ])
    
    592
    +    tv_err tv unf_ty rhs_ty = hang (text  "Let-bound tyvar unfolding not same as RHS:"
    
    593
    +                                    <+> pprTyVarWithKind tv)
    
    594
    +                                 2 (vcat [ text "Unfolding:" <+> ppr unf_ty
    
    595
    +                                         , text "RHS:      " <+> ppr rhs_ty ])
    
    590 596
     
    
    591 597
     lintLetExpr tvs (Let (NonRec bndr rhs) body)
    
    592 598
       | isId bndr
    
    ... ... @@ -3086,6 +3092,7 @@ data LintFlags
    3086 3092
            , lf_check_linearity :: Bool    -- ^ See Note [Linting linearity]
    
    3087 3093
            , lf_check_fixed_rep :: Bool    -- ^ See Note [Checking for representation polymorphism]
    
    3088 3094
            , lf_check_rubbish_lits :: Bool -- ^ See Note [Checking for rubbish literals]
    
    3095
    +       , lf_inline_type_lets   :: Bool -- ^ See Note [Linting type lets] XXX TODO
    
    3089 3096
         }
    
    3090 3097
     
    
    3091 3098
     -- See Note [Checking StaticPtrs]
    
    ... ... @@ -3505,10 +3512,12 @@ getLintFlags :: LintM LintFlags
    3505 3512
     getLintFlags = LintM $ \ env errs -> fromBoxedLResult (Just (le_flags env), errs)
    
    3506 3513
     
    
    3507 3514
     updLintFlags :: (LintFlags -> LintFlags) -> LintM a -> LintM a
    
    3508
    -updLintFlags upd_flags thing_inside
    
    3509
    -  = LintM $ \env errs ->
    
    3510
    -    let env' = env { le_flags = upd_flags (le_flags env) }
    
    3511
    -    in unLintM thing_inside env' errs
    
    3515
    +updLintFlags upd_flags
    
    3516
    +  = updLintEnv (\env -> env { le_flags = upd_flags (le_flags env) })
    
    3517
    +
    
    3518
    +updLintEnv :: (LintEnv -> LintEnv) -> LintM a -> LintM a
    
    3519
    +updLintEnv upd thing_inside
    
    3520
    +  = LintM $ \env errs -> unLintM thing_inside (upd env) errs
    
    3512 3521
     
    
    3513 3522
     checkL :: Bool -> SDoc -> LintM ()
    
    3514 3523
     checkL True  _   = return ()
    
    ... ... @@ -3634,6 +3643,17 @@ addInScopeTyCoVar tcv tcv_type thing_inside
    3634 3643
                      Just unf_ty -> setTyVarUnfolding tcv2 (substTy subst unf_ty)
    
    3635 3644
                      Nothing     -> tcv2
    
    3636 3645
     
    
    3646
    +extendTvLetSubst :: TyVar -> Type -> LintM a -> LintM a
    
    3647
    +extendTvLetSubst tv ty thing_inside
    
    3648
    +  | isJust (tyVarUnfolding_maybe tv)
    
    3649
    +  = thing_inside
    
    3650
    +  | otherwise
    
    3651
    +  = do { flags <- getLintFlags
    
    3652
    +       ; if (lf_inline_type_lets flags)
    
    3653
    +         then updLintEnv (\ env -> env { le_subst = Type.extendTvSubst (le_subst env) tv ty })
    
    3654
    +                         thing_inside
    
    3655
    +         else thing_inside }
    
    3656
    +
    
    3637 3657
     getInVarEnv :: LintM (VarEnv (InId, OutVar))
    
    3638 3658
     getInVarEnv = LintM (\env errs -> fromBoxedLResult (Just (le_in_vars env), errs))
    
    3639 3659
     
    
    ... ... @@ -3742,7 +3762,7 @@ checkBndrOccCompatibility in_bndr v_occ
    3742 3762
     sameUnfolding :: InVar   -- Binder
    
    3743 3763
                   -> InVar    -- Occurrence
    
    3744 3764
                   -> LintM Bool
    
    3745
    --- Check that any unfolding in the /occurence/ is the same as that in the /binder/
    
    3765
    +-- Check that any unfolding in the /occurrence/ is the same as that in the /binder/
    
    3746 3766
     -- An unfolding in the occurrence is optional for Ids, but compulsory for type-let-boud
    
    3747 3767
     -- TyVars.  Somewhat lazily, we only check the latter.
    
    3748 3768
     -- We also just compare them as InTypes (as we do the type of the variable);
    

  • compiler/GHC/Core/Utils.hs
    ... ... @@ -3323,11 +3323,7 @@ mkPolyAbsLams (getter,setter) bndrs body
    3323 3323
       = go emptyVarSet [] bndrs
    
    3324 3324
       where
    
    3325 3325
         wrap_bind :: Expr b -> (b,Expr b) -> Expr b
    
    3326
    -    -- wrap_bind e (bndr, rhs)  =   (\bndr.e) rhs
    
    3327
    -    -- Very like  let bndr=rhs in e
    
    3328
    -    -- but, for type-bindings at least, does not require that the occurrences
    
    3329
    -    -- of bndr have the unfolding from the let-binding
    
    3330
    -    wrap_bind e (bndr, rhs) = App (Lam bndr e) rhs
    
    3326
    +    wrap_bind e (bndr, rhs) = Let (NonRec bndr rhs) e
    
    3331 3327
     
    
    3332 3328
         go :: TyVarSet     -- Earlier TyVar bndrs that have TyVarUnfoldings
    
    3333 3329
            -> [(b,Expr b)] -- Accumulated impedence-matching bindings (reversed)
    

  • compiler/GHC/CoreToStg/Prep.hs
    ... ... @@ -1527,7 +1527,7 @@ cpeArg :: CorePrepEnv -> Demand
    1527 1527
            -> CoreArg -> UniqSM (Floats, CpeArg)
    
    1528 1528
     cpeArg env dmd arg
    
    1529 1529
       = do { (floats1, arg1) <- cpeRhsE env arg     -- arg1 can be a lambda
    
    1530
    -       ; let arg_ty = exprType arg1
    
    1530
    +       ; let arg_ty = exprType arg
    
    1531 1531
                  lev    = typeLevity arg_ty
    
    1532 1532
                  dec    = wantFloatLocal NonRecursive dmd lev floats1 arg1
    
    1533 1533
            ; (floats2, arg2) <- executeFloatDecision env dec floats1 arg1
    

  • compiler/GHC/Driver/Config/Core/Lint.hs
    ... ... @@ -119,7 +119,8 @@ perPassFlags dflags pass
    119 119
                    , lf_check_inline_loop_breakers = check_lbs
    
    120 120
                    , lf_check_static_ptrs          = check_static_ptrs
    
    121 121
                    , lf_check_linearity            = check_linearity
    
    122
    -               , lf_check_rubbish_lits         = check_rubbish }
    
    122
    +               , lf_check_rubbish_lits         = check_rubbish
    
    123
    +               , lf_inline_type_lets           = inline_type_lets }
    
    123 124
       where
    
    124 125
         -- See Note [Checking for global Ids]
    
    125 126
         check_globals = case pass of
    
    ... ... @@ -156,6 +157,11 @@ perPassFlags dflags pass
    156 157
                           CorePrep -> True
    
    157 158
                           _        -> False
    
    158 159
     
    
    160
    +    -- See Note [Linting type lets] in GHC.Core.Lint
    
    161
    +    inline_type_lets = case pass of
    
    162
    +                          CoreDesugar -> True
    
    163
    +                          _ -> False
    
    164
    +
    
    159 165
     initLintConfig :: DynFlags -> [Var] -> LintConfig
    
    160 166
     initLintConfig dflags vars =LintConfig
    
    161 167
       { l_diagOpts = initDiagOpts dflags
    
    ... ... @@ -172,4 +178,5 @@ defaultLintFlags dflags = LF { lf_check_global_ids = False
    172 178
                                  , lf_report_unsat_syns = True
    
    173 179
                                  , lf_check_fixed_rep = True
    
    174 180
                                  , lf_check_rubbish_lits = True
    
    181
    +                             , lf_inline_type_lets = False
    
    175 182
                                  }

  • compiler/GHC/HsToCore/Utils.hs
    ... ... @@ -245,6 +245,8 @@ wrapBinds [] e = e
    245 245
     wrapBinds ((new,old):prs) e = wrapBind new old (wrapBinds prs e)
    
    246 246
     
    
    247 247
     wrapBind :: Var -> Var -> CoreExpr -> CoreExpr
    
    248
    +-- Used only to line up varaibles when combining case patterns,
    
    249
    +-- in GHC.HsToCore.Match.Constructor and GHC.HsToCore.Match.Literal
    
    248 250
     wrapBind new old body   -- NB: this function must deal with term
    
    249 251
       | new==old    = body  -- variables, type variables or coercion variables
    
    250 252
       | otherwise   = Let (NonRec new (varToCoreExpr old)) body