Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC

Commits:

9 changed files:

Changes:

  • changelog.d/T27764
    1
    +section: compiler
    
    2
    +synopsis: Fix bug in ``static`` forms
    
    3
    +issues: #27664
    
    4
    +mrs: !16624
    
    5
    +description: A ``static`` form should have no free *term* variables, but it
    
    6
    +  can have free *type* variables.  Alas, the renamer does not really know what
    
    7
    +  is a term variable and what is a type variable, because of required type
    
    8
    +  arguments. This patch moves the test to the typechecker, which does know.

  • compiler/GHC/Hs/Expr.hs
    ... ... @@ -39,6 +39,7 @@ import GHC.Tc.Types.ErrCtxt
    39 39
     import GHC.Types.Id.Info ( RecSelParent )
    
    40 40
     import GHC.Types.Name
    
    41 41
     import GHC.Types.Name.Reader
    
    42
    +import GHC.Types.Name.Set( FreeNames )
    
    42 43
     import GHC.Types.Basic
    
    43 44
     import GHC.Types.Fixity
    
    44 45
     import GHC.Types.SourceText
    
    ... ... @@ -363,7 +364,9 @@ type instance XArithSeq GhcTc = PostTcExpr
    363 364
     type instance XProc          (GhcPass _) = (EpToken "proc", TokRarrow)
    
    364 365
     
    
    365 366
     type instance XStatic        GhcPs = EpToken "static"
    
    366
    -type instance XStatic        GhcRn = NoExtField
    
    367
    +type instance XStatic        GhcRn = FreeNames
    
    368
    +  -- Free variables of the body; we can't tell if they are
    
    369
    +  -- type or term variables until we are typechecking
    
    367 370
     type instance XStatic        GhcTc = (Type, HsExpr GhcTc)
    
    368 371
       -- Type of expression, and the (fromStaticPtr function)
    
    369 372
       -- These are stored for convenience as the wiring in
    

  • compiler/GHC/Rename/Expr.hs
    ... ... @@ -667,18 +667,7 @@ rnExpr e@(HsStatic _ expr)
    667 667
            -- Rename the payload
    
    668 668
            ; (expr',fvs) <- rnLExpr expr
    
    669 669
     
    
    670
    -       -- Check that the free variables of the static form are top-level defined
    
    671
    -       -- It's OK to use nonDetEltsUniqSet here as the only side effects of
    
    672
    -       -- checkClosedInStaticForm are error messages.
    
    673
    -       -- See (SF2) Note [Grand plan for static forms] in GHC.Iface.Tidy.StaticPtrTable
    
    674
    -       ; mapM_ check_fv (nonDetEltsUniqSet fvs)
    
    675
    -
    
    676
    -       ; return (HsStatic noExtField expr', fvs) }
    
    677
    -  where
    
    678
    -    check_fv :: Name -> RnM ()
    
    679
    -    -- Check for free vars not defined at top level
    
    680
    -    check_fv n = unless (isExternalName n) $
    
    681
    -                 addErrTc (TcRnStaticFormNotClosed n)
    
    670
    +       ; return (HsStatic fvs expr', fvs) }
    
    682 671
     
    
    683 672
     {-
    
    684 673
     ************************************************************************
    

  • compiler/GHC/Tc/Gen/Expr.hs
    ... ... @@ -602,13 +602,19 @@ tcExpr (HsProc x pat cmd) res_ty
    602 602
     -- and wrap (static e) in a call to
    
    603 603
     --    fromStaticPtr :: IsStatic p => StaticPtr a -> p a
    
    604 604
     
    
    605
    -tcExpr (HsStatic _ expr) res_ty
    
    605
    +tcExpr (HsStatic free_names expr) res_ty
    
    606 606
       = do  { res_ty          <- expTypeToType res_ty
    
    607 607
             ; (co, (p_ty, expr_ty)) <- matchExpectedAppTy res_ty
    
    608 608
             ; (expr', lie) <- captureConstraints $
    
    609 609
                               addErrCtxt (StaticFormCtxt expr) $
    
    610 610
                               tcCheckPolyExprNC expr expr_ty
    
    611 611
     
    
    612
    +        -- Check that the free variables of the static form are top-level defined
    
    613
    +        -- It's OK to use nonDetEltsUniqSet here as the only side effects of
    
    614
    +        -- checkClosedInStaticForm are error messages.
    
    615
    +        -- See (SF2) Note [Grand plan for static forms] in GHC.Iface.Tidy.StaticPtrTable
    
    616
    +        ; mapM_ check_free_name (nonDetEltsUniqSet free_names)
    
    617
    +
    
    612 618
             -- Emit an implication that captures the constraints of `expr`,
    
    613 619
             -- but with a `ic_info` of StaticFormSkol
    
    614 620
             -- See #13499 for an explanation of why this is the right thing to do:
    
    ... ... @@ -637,6 +643,24 @@ tcExpr (HsStatic _ expr) res_ty
    637 643
               HsStatic (static_expr_ty, mkHsWrap wrap fromStaticPtr)
    
    638 644
                        expr''
    
    639 645
             }
    
    646
    +  where
    
    647
    +    check_free_name :: Name -> TcM ()
    
    648
    +    -- Check for free /term/ vars not defined at top level
    
    649
    +    -- We use isExternalName as a proxy for top-level-defined
    
    650
    +    check_free_name n
    
    651
    +      = do { mb_thing <- tcLookupLcl_maybe n
    
    652
    +           ; case mb_thing of
    
    653
    +               Nothing  -> return ()  -- Imports, tycons, classes allowed
    
    654
    +               Just (ATcId {})  -> unless (isExternalName n) $
    
    655
    +                                   addErrTc (TcRnStaticFormNotClosed n)
    
    656
    +
    
    657
    +               Just (ATyVar {}) -> return ()  -- Free type variables are allowed
    
    658
    +
    
    659
    +                   -- Not really expecting these, but we'll get an error from
    
    660
    +                   -- elsewhere, so don't produce an error here
    
    661
    +               Just (ATcTyCon {})      -> return ()
    
    662
    +               Just (APromotionErr {}) -> return ()
    
    663
    +               Just (AGlobal {})       -> return () }
    
    640 664
     
    
    641 665
     tcExpr (HsEmbTy _ _)      _ = failWith (TcRnIllegalTypeExpr TypeKeywordSyntax)
    
    642 666
     tcExpr (HsQual _ _ _)     _ = failWith (TcRnIllegalTypeExpr ContextArrowSyntax)
    

  • testsuite/tests/rename/should_fail/RnStaticPointersFail01.stderr
    1 1
     RnStaticPointersFail01.hs:5:7: error: [GHC-88431]
    
    2
    -    ‘x’ is used in a static form but it is not defined at top level
    
    2
    +    • ‘x’ is used in a static form but it is not defined at top level
    
    3
    +    • In the expression: static x
    
    4
    +      In an equation for ‘f’: f x = static x
    
    3 5
     

  • testsuite/tests/rename/should_fail/RnStaticPointersFail03.stderr
    1 1
     RnStaticPointersFail03.hs:8:7: error: [GHC-88431]
    
    2
    -    ‘x’ is used in a static form but it is not defined at top level
    
    2
    +    • ‘x’ is used in a static form but it is not defined at top level
    
    3
    +    • In the expression: static (x . id)
    
    4
    +      In an equation for ‘f’: f x = static (x . id)
    
    3 5
     
    
    4 6
     RnStaticPointersFail03.hs:10:8: error: [GHC-88431]
    
    5
    -    ‘k’ is used in a static form but it is not defined at top level
    
    7
    +    • ‘k’ is used in a static form but it is not defined at top level
    
    8
    +    • In the expression: static (k . id)
    
    9
    +      In an equation for ‘f0’:
    
    10
    +          f0 x
    
    11
    +            = static (k . id)
    
    12
    +            where
    
    13
    +                k = const (const () x)
    
    6 14
     
    
    7 15
     RnStaticPointersFail03.hs:14:8: error: [GHC-88431]
    
    8
    -    ‘k’ is used in a static form but it is not defined at top level
    
    16
    +    • ‘k’ is used in a static form but it is not defined at top level
    
    17
    +    • In the expression: static (k . id)
    
    18
    +      In an equation for ‘f1’:
    
    19
    +          f1 x
    
    20
    +            = static (k . id)
    
    21
    +            where
    
    22
    +                k = id
    
    9 23
     
    
    10 24
     RnStaticPointersFail03.hs:19:15: error: [GHC-88431]
    
    11
    -    ‘g’ is used in a static form but it is not defined at top level
    
    25
    +    • ‘g’ is used in a static form but it is not defined at top level
    
    26
    +    • In the first argument of ‘const’, namely ‘(static (g undefined))’
    
    27
    +      In the expression: const (static (g undefined)) (h x)
    
    28
    +      In an equation for ‘f2’:
    
    29
    +          f2 x
    
    30
    +            = const (static (g undefined)) (h x)
    
    31
    +            where
    
    32
    +                g = h
    
    33
    +                h = typeOf
    
    12 34
     

  • testsuite/tests/rename/should_fail/T26545.stderr
    1 1
     T26545.hs:12:23: error: [GHC-88431]
    
    2
    -    ‘v’ is used in a static form but it is not defined at top level
    
    2
    +    • ‘v’ is used in a static form but it is not defined at top level
    
    3
    +    • In the expression: static (I# (v +# 1#))
    
    4
    +      In the expression: let v = f 3# in static (I# (v +# 1#))
    
    5
    +      In an equation for ‘h’: h x = let v = f 3# in static (I# (v +# 1#))
    
    3 6
     

  • testsuite/tests/typecheck/should_compile/T27664.hs
    1
    +{-# LANGUAGE StaticPointers, ScopedTypeVariables #-}
    
    2
    +module Repro where
    
    3
    +
    
    4
    +import Data.Typeable
    
    5
    +import GHC.StaticPtr
    
    6
    +
    
    7
    +f1 :: forall a. Typeable a => StaticPtr (a -> a)
    
    8
    +f1 = static (id :: a -> a)
    
    9
    +
    
    10
    +f2 :: forall a. Typeable a => StaticPtr (a -> a)
    
    11
    +f2 = static (id) :: StaticPtr (a->a)

  • testsuite/tests/typecheck/should_compile/all.T
    ... ... @@ -969,3 +969,4 @@ test('ExpansionQLIm', normal, compile, [''])
    969 969
     test('T23135', normal, compile, [''])
    
    970 970
     test('LazyFieldAnnotations', normal, compile, [''])
    
    971 971
     test('T27557', normal, compile, [''])
    
    972
    +test('T27664', normal, compile, [''])