From e78a57ed764c1edd4a3041268a5ad349f746ee5b Mon Sep 17 00:00:00 2001 From: Adowrath Date: Tue, 11 Jun 2024 21:29:38 +0200 Subject: [PATCH] Add documentation for GHC-38520 (Redundant Bang Patterns) Fixes #177 --- .../after/AlreadyDeconstructed.hs | 5 +++ .../before/AlreadyDeconstructed.hs | 5 +++ .../GHC-38520/alreadyDeconstructed/index.md | 21 +++++++++++ message-index/messages/GHC-38520/index.md | 22 ++++++++++++ .../strictField/after/StrictField.hs | 6 ++++ .../strictField/before/StrictField.hs | 6 ++++ .../messages/GHC-38520/strictField/index.md | 22 ++++++++++++ .../unliftedTypes/after/UnliftedTypes.hs | 17 +++++++++ .../unliftedTypes/before/UnliftedTypes.hs | 17 +++++++++ .../messages/GHC-38520/unliftedTypes/index.md | 35 +++++++++++++++++++ 10 files changed, 156 insertions(+) create mode 100644 message-index/messages/GHC-38520/alreadyDeconstructed/after/AlreadyDeconstructed.hs create mode 100644 message-index/messages/GHC-38520/alreadyDeconstructed/before/AlreadyDeconstructed.hs create mode 100644 message-index/messages/GHC-38520/alreadyDeconstructed/index.md create mode 100644 message-index/messages/GHC-38520/index.md create mode 100644 message-index/messages/GHC-38520/strictField/after/StrictField.hs create mode 100644 message-index/messages/GHC-38520/strictField/before/StrictField.hs create mode 100644 message-index/messages/GHC-38520/strictField/index.md create mode 100644 message-index/messages/GHC-38520/unliftedTypes/after/UnliftedTypes.hs create mode 100644 message-index/messages/GHC-38520/unliftedTypes/before/UnliftedTypes.hs create mode 100644 message-index/messages/GHC-38520/unliftedTypes/index.md diff --git a/message-index/messages/GHC-38520/alreadyDeconstructed/after/AlreadyDeconstructed.hs b/message-index/messages/GHC-38520/alreadyDeconstructed/after/AlreadyDeconstructed.hs new file mode 100644 index 00000000..7d05b9a8 --- /dev/null +++ b/message-index/messages/GHC-38520/alreadyDeconstructed/after/AlreadyDeconstructed.hs @@ -0,0 +1,5 @@ +module AlreadyDeconstructed where + +doubleIfTrue :: (Int, Bool) -> Int +doubleIfTrue (x, y) | y = x * 2 +doubleIfTrue x = fst x diff --git a/message-index/messages/GHC-38520/alreadyDeconstructed/before/AlreadyDeconstructed.hs b/message-index/messages/GHC-38520/alreadyDeconstructed/before/AlreadyDeconstructed.hs new file mode 100644 index 00000000..f9c65041 --- /dev/null +++ b/message-index/messages/GHC-38520/alreadyDeconstructed/before/AlreadyDeconstructed.hs @@ -0,0 +1,5 @@ +module AlreadyDeconstructed where + +doubleIfTrue :: (Int, Bool) -> Int +doubleIfTrue (x, y) | y = x * 2 +doubleIfTrue !x = fst x diff --git a/message-index/messages/GHC-38520/alreadyDeconstructed/index.md b/message-index/messages/GHC-38520/alreadyDeconstructed/index.md new file mode 100644 index 00000000..67c67dd4 --- /dev/null +++ b/message-index/messages/GHC-38520/alreadyDeconstructed/index.md @@ -0,0 +1,21 @@ +--- +title: Already deconstructed +--- + +## Warning message + +``` +AlreadyDeconstructed.hs:5:15: warning: [-Wredundant-bang-patterns] + Pattern match has redundant bang + In an equation for ‘doubleIfTrue’: doubleIfTrue x = ... + | +5 | doubleIfTrue !x = fst x + | ^ +``` + +## Explanation + +It is possible that a previous match clause already forced the evaluation of a value, +just to reject it and try later patterns. +For example, `doubleIfTrue`'s first clause already deconstructs the pair tuple, so +a bang pattern on the tuple as a whole has no effect in the second clause. \ No newline at end of file diff --git a/message-index/messages/GHC-38520/index.md b/message-index/messages/GHC-38520/index.md new file mode 100644 index 00000000..df1cbf13 --- /dev/null +++ b/message-index/messages/GHC-38520/index.md @@ -0,0 +1,22 @@ +--- +title: Redundant Bang Patterns +summary: Used a Bang Pattern that has no Effect +severity: warning +flag: -Wredundant-bang-patterns +introduced: 9.6.1 +--- + +The `BangPatterns` extension allows the user to mark (parts of) a pattern match as strict, +compared to Haskell's default of only evaluating a pattern match as little as it needs to +to determine whether to reject it or not. +This is done by prefixing the pattern with an exclamation mark, `!`. +Using bang patterns causes such values to always be strictly evaluated to Weak head normal +form (WHNF), before the rest of the matches, any guard patterns or the right-hand side +of a function clause are executed. + +However, there are cases where a bang pattern can be redundant. +Either this is because a previous match clause was already stricter, because the user is +trying to match on a strict field of a data type, or because the type of the value being +matched on is of an unlifted or unboxed type like `Int#` or `Array#`. + +In all of these cases, the Bang Pattern has no added effect, so it is redundant. \ No newline at end of file diff --git a/message-index/messages/GHC-38520/strictField/after/StrictField.hs b/message-index/messages/GHC-38520/strictField/after/StrictField.hs new file mode 100644 index 00000000..16570143 --- /dev/null +++ b/message-index/messages/GHC-38520/strictField/after/StrictField.hs @@ -0,0 +1,6 @@ +module StrictField where + +data Foo = MkFoo !Int Int + +foo :: Foo -> Foo -> () +foo !a (MkFoo b !c) = () diff --git a/message-index/messages/GHC-38520/strictField/before/StrictField.hs b/message-index/messages/GHC-38520/strictField/before/StrictField.hs new file mode 100644 index 00000000..28cf9d27 --- /dev/null +++ b/message-index/messages/GHC-38520/strictField/before/StrictField.hs @@ -0,0 +1,6 @@ +module StrictField where + +data Foo = MkFoo !Int Int + +foo :: Foo -> Foo -> () +foo !a (MkFoo !b !c) = () diff --git a/message-index/messages/GHC-38520/strictField/index.md b/message-index/messages/GHC-38520/strictField/index.md new file mode 100644 index 00000000..3a215203 --- /dev/null +++ b/message-index/messages/GHC-38520/strictField/index.md @@ -0,0 +1,22 @@ +--- +title: Strict fields +--- + +## Warning message + +``` +UnliftedTypes.hs:17:6: warning: [-Wredundant-bang-patterns] + Pattern match has redundant bang + In an equation for ‘foo’: foo a = ... + | +17 | foo !a !b !c = () + | ^ +``` + +## Explanation + +Haskell allows a user to annotate fields of a datatype as strict, by prepending +their type with an exclamation mark `!`. +Pattern matching on such a constructor forces it to WHNF, but this also automatically +forces any strict fields to evaluate to WHNF as well. +Thus, a Bang Pattern has no effect on a strict field. \ No newline at end of file diff --git a/message-index/messages/GHC-38520/unliftedTypes/after/UnliftedTypes.hs b/message-index/messages/GHC-38520/unliftedTypes/after/UnliftedTypes.hs new file mode 100644 index 00000000..3ae83e4c --- /dev/null +++ b/message-index/messages/GHC-38520/unliftedTypes/after/UnliftedTypes.hs @@ -0,0 +1,17 @@ +{-# LANGUAGE BangPatterns #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE MagicHash #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE KindSignatures #-} +{-# LANGUAGE UnboxedTuples #-} +{-# LANGUAGE UnliftedNewtypes #-} + +module UnliftedTypes where + +import GHC.Exts + +newtype MyInt :: TYPE 'IntRep where + MkMyInt :: Int# -> MyInt + +foo :: Int# -> MyInt -> (# Int, Int #) -> () +foo a b c = () diff --git a/message-index/messages/GHC-38520/unliftedTypes/before/UnliftedTypes.hs b/message-index/messages/GHC-38520/unliftedTypes/before/UnliftedTypes.hs new file mode 100644 index 00000000..0d28a4cd --- /dev/null +++ b/message-index/messages/GHC-38520/unliftedTypes/before/UnliftedTypes.hs @@ -0,0 +1,17 @@ +{-# LANGUAGE BangPatterns #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE MagicHash #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE KindSignatures #-} +{-# LANGUAGE UnboxedTuples #-} +{-# LANGUAGE UnliftedNewtypes #-} + +module UnliftedTypes where + +import GHC.Exts + +newtype MyInt :: TYPE 'IntRep where + MkMyInt :: Int# -> MyInt + +foo :: Int# -> MyInt -> (# Int, Int #) -> () +foo !a !b !c = () diff --git a/message-index/messages/GHC-38520/unliftedTypes/index.md b/message-index/messages/GHC-38520/unliftedTypes/index.md new file mode 100644 index 00000000..faeb8435 --- /dev/null +++ b/message-index/messages/GHC-38520/unliftedTypes/index.md @@ -0,0 +1,35 @@ +--- +title: Unlifted and Unboxed Types +--- + +## Warning messages + +``` +UnliftedTypes.hs:17:6: warning: [-Wredundant-bang-patterns] + Pattern match has redundant bang + In an equation for ‘foo’: foo a = ... + | +17 | foo !a !b !c = () + | ^ + +UnliftedTypes.hs:17:9: warning: [-Wredundant-bang-patterns] + Pattern match has redundant bang + In an equation for ‘foo’: foo b = ... + | +17 | foo !a !b !c = () + | ^ + +UnliftedTypes.hs:17:12: warning: [-Wredundant-bang-patterns] + Pattern match has redundant bang + In an equation for ‘foo’: foo c = ... + | +17 | foo !a !b !c = () + | ^ +``` + +## Explanation + +Forcing the evaluation of a value up to WHNF breaks down with unlifted and +unboxed types, which explicitly lack a wrapping thunk (there is no *box*), +and so values of such types are already always strict. +Thus, trying to enforce strictness via a bang pattern has no effect. \ No newline at end of file