From 0ce895dde026e68c94b84816f8942d830dc8fd0d Mon Sep 17 00:00:00 2001 From: Harendra Kumar Date: Sun, 19 Jul 2026 15:02:15 +0530 Subject: [PATCH 1/3] Remove ForbidFused and PermitFused annotations To keep things simple, we can use forbid-fused to achieve the same effect to some degree. --- src/Fusion/Plugin/Types.hs | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/Fusion/Plugin/Types.hs b/src/Fusion/Plugin/Types.hs index 4f5ba40..f172ddb 100644 --- a/src/Fusion/Plugin/Types.hs +++ b/src/Fusion/Plugin/Types.hs @@ -118,6 +118,12 @@ newtype NoFuseTypes = NoFuseTypes [Name] data NoFuse = NoFuse deriving (Eq, Data) +-- NOTE: Unboxed and other non-heap-allocated types are ignored by these +-- inspection annotations by default. The @inspect-unboxed@ plugin option turns +-- on their inclusion module-wide, which is usually sufficient. If in future +-- per-binding control is wanted instead, the names could take a @#@ suffix, +-- for example "PermitConstructions#". + -- | A GHC annotation attached to a specific top level binding (via an @ANN@ -- pragma on the binding, not on a type) that requests a fusion report for the -- types /pattern-matched/ (scrutinized, i.e. deconstructed in a @case@) in @@ -131,22 +137,18 @@ data NoFuse = NoFuse -- -- @ -- {-\# ANN function1 (ForbidPatternMatches [''Maybe]) #-} --- {-\# ANN function2 (ForbidFusedPatternMatches [''Maybe] [''Step]) #-} -- {-\# ANN function3 (PermitPatternMatches [''Int, ''IO]) #-} -- @ data InspectPatternMatches = ForbidPatternMatches [Name] - -- ^ Blocklist: report occurrences of exactly the named types found in a + -- ^ Blocklist: report occurrences of the named types found in a -- scrutinizing or deconstructing (pattern-match, i.e. @case@) position in - -- the binding, regardless of whether they are annotated with 'Fuse'. + -- the binding. When the @forbid-fused@ plugin option is on, every type + -- annotated with 'Fuse' is reported as well, with the named types added on + -- top; otherwise only exactly the named types are reported. | PermitPatternMatches [Name] -- ^ Allowlist: report every type pattern-matched in the binding except the -- named types, which may appear freely. - | ForbidFusedPatternMatches [Name] [Name] - -- ^ Report pattern-match occurrences of every type annotated with 'Fuse' - -- found in the binding -- plus any types named in the first (forbid) list, - -- minus any types named in the second (allow) list. A name present in both - -- lists is allowed. deriving (Eq, Data) -- | A GHC annotation attached to a specific top level binding (via an @ANN@ @@ -158,22 +160,18 @@ data InspectPatternMatches -- -- @ -- {-\# ANN function1 (ForbidAllocations [''Maybe]) #-} --- {-\# ANN function2 (ForbidFusedAllocations [''Maybe] [''Step]) #-} -- {-\# ANN function3 (PermitAllocations [''Int, ''IO]) #-} -- @ data InspectAllocations = ForbidAllocations [Name] - -- ^ Blocklist: report occurrences of exactly the named types found in a - -- constructing (allocating) position in the binding, regardless of whether - -- they are annotated with 'Fuse'. + -- ^ Blocklist: report occurrences of the named types found in a + -- constructing (allocating) position in the binding. When the + -- @forbid-fused@ plugin option is on, every type annotated with 'Fuse' is + -- reported as well, with the named types added on top; otherwise only + -- exactly the named types are reported. | PermitAllocations [Name] -- ^ Allowlist: report every type constructed in the binding except the -- named types, which may appear freely. - | ForbidFusedAllocations [Name] [Name] - -- ^ Report constructing occurrences of every type annotated with 'Fuse' - -- found in the binding -- plus any types named in the first (forbid) list, - -- minus any types named in the second (allow) list. A name present in both - -- lists is allowed. deriving (Eq, Data) -- | A GHC annotation attached to a specific top level binding (via an @ANN@ From 504c7ba9dc45cf315d5a9cbd05ccf7768c7c7a95 Mon Sep 17 00:00:00 2001 From: Harendra Kumar Date: Sun, 19 Jul 2026 15:21:03 +0530 Subject: [PATCH 2/3] Rename Allocations to Constructions Constructions covers the cases of unboxed types which are not really allocations but still may be in constructing positions. --- src/Fusion/Plugin/Types.hs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Fusion/Plugin/Types.hs b/src/Fusion/Plugin/Types.hs index f172ddb..571789b 100644 --- a/src/Fusion/Plugin/Types.hs +++ b/src/Fusion/Plugin/Types.hs @@ -21,7 +21,7 @@ module Fusion.Plugin.Types -- At most one annotation of each type is allowed per binding (attaching more -- than one of the same type is a compile error). Annotations of different -- types may be combined -- e.g. a binding may use both an - -- 'InspectPatternMatches' and an 'InspectAllocations' annotation to inspect + -- 'InspectPatternMatches' and an 'InspectConstructions' annotation to inspect -- both positions at once. -- ** Fusion Annotations @@ -34,7 +34,7 @@ module Fusion.Plugin.Types -- ** Inspection Annotations -- | Annotations to find fusion violations. , InspectPatternMatches(..) - , InspectAllocations(..) + , InspectConstructions(..) , InspectTypeClasses(..) , MaxCoreSize(..) @@ -153,23 +153,23 @@ data InspectPatternMatches -- | A GHC annotation attached to a specific top level binding (via an @ANN@ -- pragma on the binding, not on a type) that requests a fusion report for the --- types /allocated/ (constructed, i.e. built up) in that binding. +-- types /constructed/ (allocated, i.e. built up) in that binding. -- -- The same name rules as 'InspectPatternMatches' apply: use /type/ names -- (double quote, e.g. @''Int@), not data constructor names. -- -- @ --- {-\# ANN function1 (ForbidAllocations [''Maybe]) #-} --- {-\# ANN function3 (PermitAllocations [''Int, ''IO]) #-} +-- {-\# ANN function1 (ForbidConstructions [''Maybe]) #-} +-- {-\# ANN function3 (PermitConstructions [''Int, ''IO]) #-} -- @ -data InspectAllocations - = ForbidAllocations [Name] +data InspectConstructions + = ForbidConstructions [Name] -- ^ Blocklist: report occurrences of the named types found in a -- constructing (allocating) position in the binding. When the -- @forbid-fused@ plugin option is on, every type annotated with 'Fuse' is -- reported as well, with the named types added on top; otherwise only -- exactly the named types are reported. - | PermitAllocations [Name] + | PermitConstructions [Name] -- ^ Allowlist: report every type constructed in the binding except the -- named types, which may appear freely. deriving (Eq, Data) From a74c4a229303b3df25d06853d80408c55b3e45e7 Mon Sep 17 00:00:00 2001 From: Harendra Kumar Date: Sun, 19 Jul 2026 19:09:07 +0530 Subject: [PATCH 3/3] Improve/simplify documentation of forbid/permit anns --- src/Fusion/Plugin/Types.hs | 39 +++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/src/Fusion/Plugin/Types.hs b/src/Fusion/Plugin/Types.hs index 571789b..07c6aea 100644 --- a/src/Fusion/Plugin/Types.hs +++ b/src/Fusion/Plugin/Types.hs @@ -32,7 +32,10 @@ module Fusion.Plugin.Types , NoFuse(..) -- ** Inspection Annotations - -- | Annotations to find fusion violations. + -- | Annotations to find fusion violations. Two simple rules hold regardless + -- of any other conditions: a type explicitly listed in a @Forbid...@ + -- annotation is always forbidden; a type explicitly listed in a @Permit...@ + -- annotation is always allowed. , InspectPatternMatches(..) , InspectConstructions(..) , InspectTypeClasses(..) @@ -118,11 +121,11 @@ newtype NoFuseTypes = NoFuseTypes [Name] data NoFuse = NoFuse deriving (Eq, Data) --- NOTE: Unboxed and other non-heap-allocated types are ignored by these --- inspection annotations by default. The @inspect-unboxed@ plugin option turns --- on their inclusion module-wide, which is usually sufficient. If in future --- per-binding control is wanted instead, the names could take a @#@ suffix, --- for example "PermitConstructions#". +-- NOTE: Unboxed types are ignored by these inspection annotations by default. +-- The @inspect-unboxed@ plugin option turns on their inclusion module-wide, +-- which is usually sufficient. If in future per-binding control is wanted +-- instead, the names could take a @#@ suffix, for example +-- "PermitConstructions#". -- | A GHC annotation attached to a specific top level binding (via an @ANN@ -- pragma on the binding, not on a type) that requests a fusion report for the @@ -141,14 +144,13 @@ data NoFuse = NoFuse -- @ data InspectPatternMatches = ForbidPatternMatches [Name] - -- ^ Blocklist: report occurrences of the named types found in a + -- ^ Blocklist: names explicitly listed here are not allowed to occur in -- scrutinizing or deconstructing (pattern-match, i.e. @case@) position in - -- the binding. When the @forbid-fused@ plugin option is on, every type - -- annotated with 'Fuse' is reported as well, with the named types added on - -- top; otherwise only exactly the named types are reported. + -- the binding. When the @forbid-fused@ plugin option is enabled, types + -- annotated with 'Fuse' are implictly added to this list. | PermitPatternMatches [Name] - -- ^ Allowlist: report every type pattern-matched in the binding except the - -- named types, which may appear freely. + -- ^ Allowlist: names explicitly mentioned here are always allowed in + -- pattern matches in the binding. deriving (Eq, Data) -- | A GHC annotation attached to a specific top level binding (via an @ANN@ @@ -164,14 +166,13 @@ data InspectPatternMatches -- @ data InspectConstructions = ForbidConstructions [Name] - -- ^ Blocklist: report occurrences of the named types found in a - -- constructing (allocating) position in the binding. When the - -- @forbid-fused@ plugin option is on, every type annotated with 'Fuse' is - -- reported as well, with the named types added on top; otherwise only - -- exactly the named types are reported. + -- ^ Blocklist: names explicitly listed here are not allowed to occur in + -- constructing (usually leading to allocations) position in the binding. + -- When the @forbid-fused@ plugin option is enabled, types annotated with + -- 'Fuse' are implictly added to this list. | PermitConstructions [Name] - -- ^ Allowlist: report every type constructed in the binding except the - -- named types, which may appear freely. + -- ^ Allowlist: names explicitly mentioned here are always allowed in + -- constructing positions in the binding. deriving (Eq, Data) -- | A GHC annotation attached to a specific top level binding (via an @ANN@