summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland Senn <rsx@bluewin.ch>2020-06-17 17:18:26 +0200
committerMarge Bot <ben+marge-bot@smart-cactus.org>2020-06-25 03:54:48 -0400
commitfe281b27d544920a2c2ddc00f6284006b85ab294 (patch)
tree60b47aea661bc80c8b3b714aaa212a95f13425a3
parentc50ef26edaa537c0a13ac1a574632f9078c5671b (diff)
downloadhaskell-fe281b27d544920a2c2ddc00f6284006b85ab294.tar.gz
Enable maxBound checks for OverloadedLists (Fixes #18172)
Consider the Literal `[256] :: [Data.Word.Word8]` When the `OverloadedLists` extension is not active, then the `ol_ext` field in the `OverLitTc` record that is passed to the function `getIntegralLit` contains the type `Word8`. This is a simple type, and we can use its type constructor immediately for the `warnAboutOverflowedLiterals` function. When the `OverloadedLists` extension is active, then the `ol_ext` field contains the type family `Item [Word8]`. The function `nomaliseType` is used to convert it to the needed type `Word8`.
-rw-r--r--compiler/GHC/HsToCore/Expr.hs10
-rw-r--r--compiler/GHC/HsToCore/Match/Literal.hs82
-rw-r--r--testsuite/tests/deSugar/should_run/T18172.hs13
-rw-r--r--testsuite/tests/deSugar/should_run/T18172.script22
-rw-r--r--testsuite/tests/deSugar/should_run/T18172.stderr47
-rw-r--r--testsuite/tests/deSugar/should_run/T18172.stdout14
-rw-r--r--testsuite/tests/deSugar/should_run/all.T1
7 files changed, 162 insertions, 27 deletions
diff --git a/compiler/GHC/HsToCore/Expr.hs b/compiler/GHC/HsToCore/Expr.hs
index ff23a9c168..6b55926af3 100644
--- a/compiler/GHC/HsToCore/Expr.hs
+++ b/compiler/GHC/HsToCore/Expr.hs
@@ -945,8 +945,9 @@ dsArithSeq :: PostTcExpr -> (ArithSeqInfo GhcTc) -> DsM CoreExpr
dsArithSeq expr (From from)
= App <$> dsExpr expr <*> dsLExprNoLP from
dsArithSeq expr (FromTo from to)
- = do dflags <- getDynFlags
- warnAboutEmptyEnumerations dflags from Nothing to
+ = do fam_envs <- dsGetFamInstEnvs
+ dflags <- getDynFlags
+ warnAboutEmptyEnumerations fam_envs dflags from Nothing to
expr' <- dsExpr expr
from' <- dsLExprNoLP from
to' <- dsLExprNoLP to
@@ -954,8 +955,9 @@ dsArithSeq expr (FromTo from to)
dsArithSeq expr (FromThen from thn)
= mkApps <$> dsExpr expr <*> mapM dsLExprNoLP [from, thn]
dsArithSeq expr (FromThenTo from thn to)
- = do dflags <- getDynFlags
- warnAboutEmptyEnumerations dflags from (Just thn) to
+ = do fam_envs <- dsGetFamInstEnvs
+ dflags <- getDynFlags
+ warnAboutEmptyEnumerations fam_envs dflags from (Just thn) to
expr' <- dsExpr expr
from' <- dsLExprNoLP from
thn' <- dsLExprNoLP thn
diff --git a/compiler/GHC/HsToCore/Match/Literal.hs b/compiler/GHC/HsToCore/Match/Literal.hs
index cb38aef33a..ed4ceafa05 100644
--- a/compiler/GHC/HsToCore/Match/Literal.hs
+++ b/compiler/GHC/HsToCore/Match/Literal.hs
@@ -55,6 +55,7 @@ import GHC.Driver.Session
import GHC.Utils.Misc
import GHC.Data.FastString
import qualified GHC.LanguageExtensions as LangExt
+import GHC.Core.FamInstEnv ( FamInstEnvs, normaliseType )
import Control.Monad
import Data.Int
@@ -169,14 +170,17 @@ conversionNames
warnAboutOverflowedOverLit :: HsOverLit GhcTc -> DsM ()
warnAboutOverflowedOverLit hsOverLit = do
dflags <- getDynFlags
- warnAboutOverflowedLiterals dflags (getIntegralLit hsOverLit)
+ fam_envs <- dsGetFamInstEnvs
+ warnAboutOverflowedLiterals dflags $
+ getIntegralLit hsOverLit >>= getNormalisedTyconName fam_envs
-- | Emit warnings on integral literals which overflow the bounds implied by
-- their type.
warnAboutOverflowedLit :: HsLit GhcTc -> DsM ()
warnAboutOverflowedLit hsLit = do
dflags <- getDynFlags
- warnAboutOverflowedLiterals dflags (getSimpleIntegralLit hsLit)
+ warnAboutOverflowedLiterals dflags $
+ getSimpleIntegralLit hsLit >>= getTyconName
-- | Emit warnings on integral literals which overflow the bounds implied by
-- their type.
@@ -254,15 +258,17 @@ We get an erroneous suggestion for
but perhaps that does not matter too much.
-}
-warnAboutEmptyEnumerations :: DynFlags -> LHsExpr GhcTc -> Maybe (LHsExpr GhcTc)
+warnAboutEmptyEnumerations :: FamInstEnvs -> DynFlags -> LHsExpr GhcTc
+ -> Maybe (LHsExpr GhcTc)
-> LHsExpr GhcTc -> DsM ()
-- ^ Warns about @[2,3 .. 1]@ which returns the empty list.
-- Only works for integral types, not floating point.
-warnAboutEmptyEnumerations dflags fromExpr mThnExpr toExpr
+warnAboutEmptyEnumerations fam_envs dflags fromExpr mThnExpr toExpr
| wopt Opt_WarnEmptyEnumerations dflags
- , Just (from,tc) <- getLHsIntegralLit fromExpr
- , Just mThn <- traverse getLHsIntegralLit mThnExpr
- , Just (to,_) <- getLHsIntegralLit toExpr
+ , Just from_ty@(from,_) <- getLHsIntegralLit fromExpr
+ , Just (_, tc) <- getNormalisedTyconName fam_envs from_ty
+ , Just mThn <- traverse getLHsIntegralLit mThnExpr
+ , Just (to,_) <- getLHsIntegralLit toExpr
, let check :: forall a. (Enum a, Num a) => Proxy a -> DsM ()
check _proxy
= when (null enumeration) $
@@ -292,7 +298,7 @@ warnAboutEmptyEnumerations dflags fromExpr mThnExpr toExpr
| otherwise = return ()
-getLHsIntegralLit :: LHsExpr GhcTc -> Maybe (Integer, Name)
+getLHsIntegralLit :: LHsExpr GhcTc -> Maybe (Integer, Type)
-- ^ See if the expression is an 'Integral' literal.
-- Remember to look through automatically-added tick-boxes! (#8384)
getLHsIntegralLit (L _ (HsPar _ e)) = getLHsIntegralLit e
@@ -302,26 +308,56 @@ getLHsIntegralLit (L _ (HsOverLit _ over_lit)) = getIntegralLit over_lit
getLHsIntegralLit (L _ (HsLit _ lit)) = getSimpleIntegralLit lit
getLHsIntegralLit _ = Nothing
--- | If 'Integral', extract the value and type name of the overloaded literal.
-getIntegralLit :: HsOverLit GhcTc -> Maybe (Integer, Name)
+-- | If 'Integral', extract the value and type of the overloaded literal.
+-- See Note [Literals and the OverloadedLists extension]
+getIntegralLit :: HsOverLit GhcTc -> Maybe (Integer, Type)
getIntegralLit (OverLit { ol_val = HsIntegral i, ol_ext = OverLitTc _ ty })
- | Just tc <- tyConAppTyCon_maybe ty
- = Just (il_value i, tyConName tc)
+ = Just (il_value i, ty)
getIntegralLit _ = Nothing
--- | If 'Integral', extract the value and type name of the non-overloaded
--- literal.
-getSimpleIntegralLit :: HsLit GhcTc -> Maybe (Integer, Name)
-getSimpleIntegralLit (HsInt _ IL{ il_value = i }) = Just (i, intTyConName)
-getSimpleIntegralLit (HsIntPrim _ i) = Just (i, intPrimTyConName)
-getSimpleIntegralLit (HsWordPrim _ i) = Just (i, wordPrimTyConName)
-getSimpleIntegralLit (HsInt64Prim _ i) = Just (i, int64PrimTyConName)
-getSimpleIntegralLit (HsWord64Prim _ i) = Just (i, word64PrimTyConName)
-getSimpleIntegralLit (HsInteger _ i ty)
- | Just tc <- tyConAppTyCon_maybe ty
- = Just (i, tyConName tc)
+-- | If 'Integral', extract the value and type of the non-overloaded literal.
+getSimpleIntegralLit :: HsLit GhcTc -> Maybe (Integer, Type)
+getSimpleIntegralLit (HsInt _ IL{ il_value = i }) = Just (i, intTy)
+getSimpleIntegralLit (HsIntPrim _ i) = Just (i, intPrimTy)
+getSimpleIntegralLit (HsWordPrim _ i) = Just (i, wordPrimTy)
+getSimpleIntegralLit (HsInt64Prim _ i) = Just (i, int64PrimTy)
+getSimpleIntegralLit (HsWord64Prim _ i) = Just (i, word64PrimTy)
+getSimpleIntegralLit (HsInteger _ i ty) = Just (i, ty)
getSimpleIntegralLit _ = Nothing
+-- | Convert a pair (Integer, Type) to (Integer, Name) after eventually
+-- normalising the type
+getNormalisedTyconName :: FamInstEnvs -> (Integer, Type) -> Maybe (Integer, Name)
+getNormalisedTyconName fam_envs (i,ty)
+ | Just tc <- tyConAppTyCon_maybe (normaliseNominal fam_envs ty)
+ = Just (i, tyConName tc)
+ | otherwise = Nothing
+ where
+ normaliseNominal :: FamInstEnvs -> Type -> Type
+ normaliseNominal fam_envs ty = snd $ normaliseType fam_envs Nominal ty
+
+-- | Convert a pair (Integer, Type) to (Integer, Name) without normalising
+-- the type
+getTyconName :: (Integer, Type) -> Maybe (Integer, Name)
+getTyconName (i,ty)
+ | Just tc <- tyConAppTyCon_maybe ty = Just (i, tyConName tc)
+ | otherwise = Nothing
+
+{-
+Note [Literals and the OverloadedLists extension]
+~~~~
+Consider the Literal `[256] :: [Data.Word.Word8]`
+
+When the `OverloadedLists` extension is not active, then the `ol_ext` field
+in the `OverLitTc` record that is passed to the function `getIntegralLit`
+contains the type `Word8`. This is a simple type, and we can use its
+type constructor immediately for the `warnAboutOverflowedLiterals` function.
+
+When the `OverloadedLists` extension is active, then the `ol_ext` field
+contains the type family `Item [Word8]`. The function `nomaliseType` is used
+to convert it to the needed type `Word8`.
+-}
+
{-
************************************************************************
* *
diff --git a/testsuite/tests/deSugar/should_run/T18172.hs b/testsuite/tests/deSugar/should_run/T18172.hs
new file mode 100644
index 0000000000..afd21fc9f0
--- /dev/null
+++ b/testsuite/tests/deSugar/should_run/T18172.hs
@@ -0,0 +1,13 @@
+{-# LANGUAGE TypeFamilies #-}
+module T18172 where
+
+import Data.Word
+import GHC.Exts
+
+data Wombat = Wombat [Word8]
+ deriving Show
+
+instance IsList Wombat where
+ type Item Wombat = Word8
+ fromList xs = Wombat xs
+ toList (Wombat xs)= xs
diff --git a/testsuite/tests/deSugar/should_run/T18172.script b/testsuite/tests/deSugar/should_run/T18172.script
new file mode 100644
index 0000000000..f0226e85c4
--- /dev/null
+++ b/testsuite/tests/deSugar/should_run/T18172.script
@@ -0,0 +1,22 @@
+import Data.Word
+[-1] :: [Word8]
+[256] :: [Word8]
+:set -XOverloadedLists
+[-2] :: [Word8]
+[257] :: [Word8]
+import Data.List.NonEmpty
+[-3] :: NonEmpty Word8
+[258] :: NonEmpty Word8
+import Control.Applicative
+ZipList [-4] :: ZipList Word8
+ZipList [259] :: ZipList Word8
+
+[Just 260] :: [Maybe Word8]
+[Just [Just 261]] :: [Maybe ([Maybe Word8])]
+[(262, 65536)] :: [(Word8, Word16)]
+
+[-5..100]::[Word8]
+[100..263]::[Word8]
+
+:l T18172.hs
+Wombat [4, 264, 10]
diff --git a/testsuite/tests/deSugar/should_run/T18172.stderr b/testsuite/tests/deSugar/should_run/T18172.stderr
new file mode 100644
index 0000000000..f5771d8121
--- /dev/null
+++ b/testsuite/tests/deSugar/should_run/T18172.stderr
@@ -0,0 +1,47 @@
+<interactive>:2:3: warning: [-Woverflowed-literals (in -Wdefault)]
+ Literal -1 is out of the Word8 range 0..255
+
+<interactive>:3:2: warning: [-Woverflowed-literals (in -Wdefault)]
+ Literal 256 is out of the Word8 range 0..255
+
+<interactive>:5:3: warning: [-Woverflowed-literals (in -Wdefault)]
+ Literal -2 is out of the Word8 range 0..255
+
+<interactive>:6:2: warning: [-Woverflowed-literals (in -Wdefault)]
+ Literal 257 is out of the Word8 range 0..255
+
+<interactive>:8:3: warning: [-Woverflowed-literals (in -Wdefault)]
+ Literal -3 is out of the Word8 range 0..255
+
+<interactive>:9:2: warning: [-Woverflowed-literals (in -Wdefault)]
+ Literal 258 is out of the Word8 range 0..255
+
+<interactive>:11:11: warning: [-Woverflowed-literals (in -Wdefault)]
+ Literal -4 is out of the Word8 range 0..255
+
+<interactive>:12:10: warning: [-Woverflowed-literals (in -Wdefault)]
+ Literal 259 is out of the Word8 range 0..255
+
+<interactive>:14:7: warning: [-Woverflowed-literals (in -Wdefault)]
+ Literal 260 is out of the Word8 range 0..255
+
+<interactive>:15:13: warning: [-Woverflowed-literals (in -Wdefault)]
+ Literal 261 is out of the Word8 range 0..255
+
+<interactive>:16:3: warning: [-Woverflowed-literals (in -Wdefault)]
+ Literal 262 is out of the Word8 range 0..255
+
+<interactive>:16:8: warning: [-Woverflowed-literals (in -Wdefault)]
+ Literal 65536 is out of the Word16 range 0..65535
+
+<interactive>:18:3: warning: [-Woverflowed-literals (in -Wdefault)]
+ Literal -5 is out of the Word8 range 0..255
+
+<interactive>:19:1: warning: [-Wempty-enumerations (in -Wdefault)]
+ Enumeration is empty
+
+<interactive>:19:7: warning: [-Woverflowed-literals (in -Wdefault)]
+ Literal 263 is out of the Word8 range 0..255
+
+<interactive>:22:12: warning: [-Woverflowed-literals (in -Wdefault)]
+ Literal 264 is out of the Word8 range 0..255
diff --git a/testsuite/tests/deSugar/should_run/T18172.stdout b/testsuite/tests/deSugar/should_run/T18172.stdout
new file mode 100644
index 0000000000..8f30df2597
--- /dev/null
+++ b/testsuite/tests/deSugar/should_run/T18172.stdout
@@ -0,0 +1,14 @@
+[255]
+[0]
+[254]
+[1]
+253 :| []
+2 :| []
+ZipList {getZipList = [252]}
+ZipList {getZipList = [3]}
+[Just 4]
+[Just [Just 5]]
+[(6,0)]
+[]
+[]
+Wombat [4,8,10]
diff --git a/testsuite/tests/deSugar/should_run/all.T b/testsuite/tests/deSugar/should_run/all.T
index 214f088aea..6245f9caf5 100644
--- a/testsuite/tests/deSugar/should_run/all.T
+++ b/testsuite/tests/deSugar/should_run/all.T
@@ -65,3 +65,4 @@ test('T11747', normal, compile_and_run, ['-dcore-lint'])
test('T12595', normal, compile_and_run, [''])
test('T13285', normal, compile_and_run, [''])
test('T18151', normal, compile_and_run, [''])
+test('T18172', [], ghci_script, ['T18172.script'])