Skip to content
  • Andrei Borzenkov's avatar
    2afbddb0
    Type patterns (#22478, #18986) · 2afbddb0
    Andrei Borzenkov authored
    Improved name resolution and type checking of type patterns in constructors:
    
    1. HsTyPat: a new dedicated data type that represents type patterns in
       HsConPatDetails instead of reusing HsPatSigType
    
    2. rnHsTyPat: a new function that renames a type
       pattern and collects its binders into three groups:
        - explicitly bound type variables, excluding locally bound
          variables
        - implicitly bound type variables from kind signatures
          (only if ScopedTypeVariables are enabled)
        - named wildcards (only from kind signatures)
    2a. rnHsPatSigTypeBindingVars: removed in favour of rnHsTyPat
    2b. rnImplcitTvBndrs: removed because no longer needed
    
    3. collect_pat: updated to collect type variable binders from type patterns
       (this means that types and terms use the same infrastructure to detect
       conflicting bindings, unused variables and name shadowing)
    3a. CollVarTyVarBinders: a new CollectFlag constructor that enables
        collection of type variables
    
    4. tcHsTyPat: a new function that typechecks type patterns, capable of
       handling polymorphic kinds.
       See Note [Type patterns: binders and unifiers]
    
    Examples of code that is now accepted:
    
       f = \(P @a) -> \(P @a) -> ...  -- triggers -Wname-shadowing
    
       g :: forall a. Proxy a -> ...
       g (P @a) = ...                 -- also triggers -Wname-shadowing
    
       h (P @($(TH.varT (TH.mkName "t")))) = ...
                                      -- t is bound at splice time
    
       j (P @(a :: (x,x))) = ...      -- (x,x) is no longer rejected
    
       data T where
         MkT :: forall (f :: forall k. k -> Type).
           f Int -> f Maybe -> T
       k :: T -> ()
       k (MkT @f (x :: f Int) (y :: f Maybe)) = ()
                                      -- f :: forall k. k -> Type
    
    Examples of code that is rejected with better error messages:
    
      f (Left @a @a _) = ...
      -- new message:
      --     • Conflicting definitions for ‘a’
      --       Bound at: Test.hs:1:11
      --                 Test.hs:1:14
    
    Examples of code that is now rejected:
    
      {-# OPTIONS_GHC -Werror=unused-matches #-}
      f (P @a) = ()
      -- Defined but not used: type variable ‘a’
    2afbddb0
    Type patterns (#22478, #18986)
    Andrei Borzenkov authored
    Improved name resolution and type checking of type patterns in constructors:
    
    1. HsTyPat: a new dedicated data type that represents type patterns in
       HsConPatDetails instead of reusing HsPatSigType
    
    2. rnHsTyPat: a new function that renames a type
       pattern and collects its binders into three groups:
        - explicitly bound type variables, excluding locally bound
          variables
        - implicitly bound type variables from kind signatures
          (only if ScopedTypeVariables are enabled)
        - named wildcards (only from kind signatures)
    2a. rnHsPatSigTypeBindingVars: removed in favour of rnHsTyPat
    2b. rnImplcitTvBndrs: removed because no longer needed
    
    3. collect_pat: updated to collect type variable binders from type patterns
       (this means that types and terms use the same infrastructure to detect
       conflicting bindings, unused variables and name shadowing)
    3a. CollVarTyVarBinders: a new CollectFlag constructor that enables
        collection of type variables
    
    4. tcHsTyPat: a new function that typechecks type patterns, capable of
       handling polymorphic kinds.
       See Note [Type patterns: binders and unifiers]
    
    Examples of code that is now accepted:
    
       f = \(P @a) -> \(P @a) -> ...  -- triggers -Wname-shadowing
    
       g :: forall a. Proxy a -> ...
       g (P @a) = ...                 -- also triggers -Wname-shadowing
    
       h (P @($(TH.varT (TH.mkName "t")))) = ...
                                      -- t is bound at splice time
    
       j (P @(a :: (x,x))) = ...      -- (x,x) is no longer rejected
    
       data T where
         MkT :: forall (f :: forall k. k -> Type).
           f Int -> f Maybe -> T
       k :: T -> ()
       k (MkT @f (x :: f Int) (y :: f Maybe)) = ()
                                      -- f :: forall k. k -> Type
    
    Examples of code that is rejected with better error messages:
    
      f (Left @a @a _) = ...
      -- new message:
      --     • Conflicting definitions for ‘a’
      --       Bound at: Test.hs:1:11
      --                 Test.hs:1:14
    
    Examples of code that is now rejected:
    
      {-# OPTIONS_GHC -Werror=unused-matches #-}
      f (P @a) = ()
      -- Defined but not used: type variable ‘a’
Loading