Commit 981bf471 authored by Ben Gamari's avatar Ben Gamari 🐢

Normalize the element type of ListPat, fix #14547

The element type of `List` maybe a type family instacen, rather than a
trivial type.
For example in Trac #14547,

```
{-# LANGUAGE TypeFamilies, OverloadedLists #-}

class Foo f where
        type It f
        foo :: [It f] -> f

data List a = Empty | a :! List a deriving Show

instance Foo (List a) where
        type It (List a) = a
        foo [] = Empty
        foo (x : xs) = x :! foo xs
```

Here the element type of `[]` is `It (List a)`, we should also normalize
it as `a`.

Test Plan: make test TEST="T14547"

Reviewers: bgamari

Reviewed By: bgamari

Subscribers: thomie, carter

GHC Trac Issues: #14547

Differential Revision: https://phabricator.haskell.org/D4624
parent 280de0c1
...@@ -790,10 +790,13 @@ translatePat fam_insts pat = case pat of ...@@ -790,10 +790,13 @@ translatePat fam_insts pat = case pat of
-- overloaded list -- overloaded list
ListPat (ListPatTc elem_ty (Just (pat_ty, _to_list))) lpats ListPat (ListPatTc elem_ty (Just (pat_ty, _to_list))) lpats
| Just e_ty <- splitListTyConApp_maybe pat_ty | Just e_ty <- splitListTyConApp_maybe pat_ty
, (_, norm_e_ty) <- normaliseType fam_insts Nominal e_ty
-- e_ty can be a type family instance, like
-- `It (List a)`, but we prefer `a`, see Trac #14547
, (_, norm_elem_ty) <- normaliseType fam_insts Nominal elem_ty , (_, norm_elem_ty) <- normaliseType fam_insts Nominal elem_ty
-- elem_ty is frequently something like -- elem_ty is frequently something like
-- `Item [Int]`, but we prefer `Int` -- `Item [Int]`, but we prefer `Int`
, norm_elem_ty `eqType` e_ty -> , norm_elem_ty `eqType` norm_e_ty ->
-- We have to ensure that the element types are exactly the same. -- We have to ensure that the element types are exactly the same.
-- Otherwise, one may give an instance IsList [Int] (more specific than -- Otherwise, one may give an instance IsList [Int] (more specific than
-- the default IsList [a]) with a different implementation for `toList' -- the default IsList [a]) with a different implementation for `toList'
......
{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE TypeFamilies #-}
module T14547 where
class Foo f where
type It f
foo :: [It f] -> f
data List a = Empty | a :! List a deriving Show
instance Foo (List a) where
type It (List a) = a
foo [] = Empty
foo (x : xs) = x :! foo xs
...@@ -100,6 +100,7 @@ test('T13290', normal, compile, ['']) ...@@ -100,6 +100,7 @@ test('T13290', normal, compile, [''])
test('T13257', normal, compile, ['']) test('T13257', normal, compile, [''])
test('T13870', normal, compile, ['']) test('T13870', normal, compile, [''])
test('T14135', normal, compile, ['']) test('T14135', normal, compile, [''])
test('T14547', normal, compile, ['-Wincomplete-patterns'])
test('T14773a', normal, compile, ['-Wincomplete-patterns']) test('T14773a', normal, compile, ['-Wincomplete-patterns'])
test('T14773b', normal, compile, ['-Wincomplete-patterns']) test('T14773b', normal, compile, ['-Wincomplete-patterns'])
test('T14815', [], run_command, ['$MAKE -s --no-print-directory T14815']) test('T14815', [], run_command, ['$MAKE -s --no-print-directory T14815'])
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment