Skip to content

CPR is overly conservative on recursive types as witnessed with ghc-9.4 on a TH derived JSON instance.

I'm looking at the module Auto.T.BigRecord from aeson compiled with -O2 -fexpose-all-unfoldings -fspecialise-aggressively in ghc-9.4.4

And for the toJSON method derived for the BigRecord type (stripped by a few fields) I see this core:

-- RHS size: {terms: 51, types: 25, coercions: 13, joins: 0/0}
Auto.T.BigRecord.$w$ctoJSON [InlPrag=[2]]
  :: ghc-prim:GHC.Prim.Int#
     -> ghc-prim:GHC.Prim.Int#
     -> ghc-prim:GHC.Prim.Int#
     -> ghc-prim:GHC.Prim.Int#
     -> ghc-prim:GHC.Prim.Int#
     -> Value
[GblId,
 Arity=5,
 Str=<L><L><L><L><L>,
 Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True,
         WorkFree=True, Expandable=True,
         Guidance=IF_ARGS [0 0 0 0 0] 290 10}]
Auto.T.BigRecord.$w$ctoJSON
  = \ (ww_s9He :: ghc-prim:GHC.Prim.Int#)
      (ww1_s9Hf :: ghc-prim:GHC.Prim.Int#)
      (ww2_s9Hg :: ghc-prim:GHC.Prim.Int#)
      (ww3_s9Hh :: ghc-prim:GHC.Prim.Int#)
      (ww4_s9Hi :: ghc-prim:GHC.Prim.Int#) ->
      case Data.Aeson.KeyMap.$fArbitrary1KeyMap_$sfromList
             @Value
             (ghc-prim:GHC.Types.:
                @Data.Aeson.Types.Internal.Pair
                (Auto.T.BigRecord.$fFromJSONBigRecord10
                 `cast` (Sym (Data.Aeson.Key.N:Key[0])
                         :: Data.Text.Internal.Text ~R# Key),
                 Data.Aeson.Types.Internal.Number
                   (Data.Scientific.Scientific (GHC.Num.Integer.IS ww_s9He) 0#))
                (ghc-prim:GHC.Types.:
                   @Data.Aeson.Types.Internal.Pair
                   (Auto.T.BigRecord.$fFromJSONBigRecord8
                    `cast` (Sym (Data.Aeson.Key.N:Key[0])
                            :: Data.Text.Internal.Text ~R# Key),
                    Data.Aeson.Types.Internal.Number
                      (Data.Scientific.Scientific (GHC.Num.Integer.IS ww1_s9Hf) 0#))
                   (ghc-prim:GHC.Types.:
                      @Data.Aeson.Types.Internal.Pair
                      (Auto.T.BigRecord.$fFromJSONBigRecord6
                       `cast` (Sym (Data.Aeson.Key.N:Key[0])
                               :: Data.Text.Internal.Text ~R# Key),
                       Data.Aeson.Types.Internal.Number
                         (Data.Scientific.Scientific (GHC.Num.Integer.IS ww2_s9Hg) 0#))
                      (ghc-prim:GHC.Types.:
                         @Data.Aeson.Types.Internal.Pair
                         (Auto.T.BigRecord.$fFromJSONBigRecord4
                          `cast` (Sym (Data.Aeson.Key.N:Key[0])
                                  :: Data.Text.Internal.Text ~R# Key),
                          Data.Aeson.Types.Internal.Number
                            (Data.Scientific.Scientific (GHC.Num.Integer.IS ww3_s9Hh) 0#))
                         (ghc-prim:GHC.Types.:
                            @Data.Aeson.Types.Internal.Pair
                            (Auto.T.BigRecord.$fFromJSONBigRecord2
                             `cast` (Sym (Data.Aeson.Key.N:Key[0])
                                     :: Data.Text.Internal.Text ~R# Key),
                             Data.Aeson.Types.Internal.Number
                               (Data.Scientific.Scientific (GHC.Num.Integer.IS ww4_s9Hi) 0#))
                            (ghc-prim:GHC.Types.[] @Data.Aeson.Types.Internal.Pair))))))
      of nt_i8wJ
      { __DEFAULT ->
      Data.Aeson.Types.Internal.Object
        (nt_i8wJ
         `cast` (Sym (Data.Aeson.KeyMap.N:KeyMap[0]) <Value>_N
                 :: Data.Map.Internal.Map Key Value
                    ~R# Data.Aeson.KeyMap.KeyMap Value))
      }

I'm confused why we don't get CPR for the result here. Clearly the application of Object nt_i8wJ should qualify for CPR as I understand it.

I assume the cast isn't properly handled somewhere in the analysis. I'm currently looking into the code but it might be obvious to you @sgraf812 if you have the time to take a look.

This used to work with ghc-8.10 I haven't checked versions in between.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information