Simon Jakobi pushed to branch wip/sjakobi/T27628-rebox-warning at Glasgow Haskell Compiler / GHC
Commits:
-
83433a7d
by Simon Jakobi at 2026-08-24T09:59:37+02:00
-
634390dc
by Simon Jakobi at 2026-08-24T17:34:52+02:00
-
1ec581aa
by Simon Jakobi at 2026-08-24T18:14:23+02:00
-
15d14c01
by Simon Jakobi at 2026-08-24T22:07:26+02:00
-
ba495af1
by Simon Jakobi at 2026-08-24T22:28:02+02:00
15 changed files:
- changelog.d/27628
- compiler/GHC/Core/Opt/SpecConstr.hs
- docs/users_guide/using-warnings.rst
- testsuite/tests/simplCore/should_compile/T27628.stderr
- testsuite/tests/simplCore/should_compile/T27628b.stderr
- testsuite/tests/simplCore/should_compile/T27628f.stderr
- testsuite/tests/simplCore/should_compile/T27628g.stderr
- testsuite/tests/simplCore/should_compile/T27628h.stderr
- testsuite/tests/simplCore/should_compile/T27628i.stderr
- testsuite/tests/simplCore/should_compile/T27628j.stderr
- testsuite/tests/simplCore/should_compile/T27628k.stderr
- testsuite/tests/simplCore/should_compile/T27628l.stderr
- + testsuite/tests/simplCore/should_compile/T27628m.hs
- + testsuite/tests/simplCore/should_compile/T27628m.stderr
- testsuite/tests/simplCore/should_compile/all.T
Changes:
| ... | ... | @@ -7,3 +7,4 @@ description: |
| 7 | 7 | re-allocates the constructor ("reboxing"). Reboxing can increase
|
| 8 | 8 | allocation and defeat sharing schemes based on pointer equality.
|
| 9 | 9 | issues: #27628
|
| 10 | +mrs: !7 |
| ... | ... | @@ -827,9 +827,9 @@ specConstrProgram guts |
| 827 | 827 | |
| 828 | 828 | -- Merge warnings that would render identically: same occurrence
|
| 829 | 829 | -- name, type, parent, displayed location, recursivity, and
|
| 830 | - -- patterns. The reader could not tell them apart, so printing
|
|
| 831 | - -- both is noise; see Note [Reboxing warning]. Callers are
|
|
| 832 | - -- aggregated, not compared.
|
|
| 830 | + -- patterns (with their spec signatures). The reader could not
|
|
| 831 | + -- tell them apart, so printing both is noise; see
|
|
| 832 | + -- Note [Reboxing warning]. Callers are aggregated, not compared.
|
|
| 833 | 833 | same_render (SpecReboxed fn1 ty1 p1 r1 pats1 _) (SpecReboxed fn2 ty2 p2 r2 pats2 _)
|
| 834 | 834 | = getOccName fn1 == getOccName fn2 && p1 == p2
|
| 835 | 835 | && nameSrcSpan (rebox_loc_name fn1 p1) == nameSrcSpan (rebox_loc_name fn2 p2)
|
| ... | ... | @@ -840,7 +840,11 @@ specConstrProgram guts |
| 840 | 840 | (sortBy cmpReboxedPat pats2))
|
| 841 | 841 | same_render _ _ = False
|
| 842 | 842 | |
| 843 | - same_pat p1 p2 = cmpReboxedPat p1 p2 == EQ
|
|
| 843 | + -- Spec signatures of merge candidates are alpha-equivalent copies,
|
|
| 844 | + -- so eqType; a mismatch just leaves two warnings unmerged
|
|
| 845 | + same_pat p1@(ReboxedPat _ _ occ1 sty1) p2@(ReboxedPat _ _ occ2 sty2)
|
|
| 846 | + = cmpReboxedPat p1 p2 == EQ
|
|
| 847 | + && occ1 == occ2 && sty1 `eqType` sty2
|
|
| 844 | 848 | |
| 845 | 849 | -- Recursivity as displayed: siblings compare by occurrence name,
|
| 846 | 850 | -- so span-less copies of one mutual group still merge
|
| ... | ... | @@ -863,25 +867,25 @@ specConstrProgram guts |
| 863 | 867 | rebox_msg w@(SpecFailForcedArgCount {}) = pprPanic "rebox_msg" (ppr w)
|
| 864 | 868 | rebox_msg (SpecReboxed fn ty mb_parent recur pats callers)
|
| 865 | 869 | = vcat [ hang (text "SpecConstr specialised") 2
|
| 866 | - (quotes (ppr fn <+> dcolon <+> pp_ty))
|
|
| 870 | + (quotes (ppr fn <+> dcolon <+> pp_ty ty))
|
|
| 867 | 871 | , nest 2 $ vcat $ catMaybes
|
| 868 | 872 | [ Just (fact "source:" pp_source)
|
| 869 | 873 | , Just (fact "recursivity:" pp_recur)
|
| 870 | 874 | , fact "called from:" <$> pp_callers
|
| 871 | - , Just (fact pats_label pp_pats) ]
|
|
| 875 | + , Just (text pats_label $$ nest 2 pp_pats) ]
|
|
| 872 | 876 | , pp_trailer
|
| 873 | - , text "See -Wspec-constr-reboxing in the users guide for possible remedies." ]
|
|
| 877 | + , text "See -Wspec-constr-reboxing in the user's guide for possible remedies." ]
|
|
| 874 | 878 | where
|
| 875 | 879 | -- Aligned label column; $$ overlaps, so a multi-line value keeps
|
| 876 | 880 | -- its lines aligned under the first
|
| 877 | - fact l v = text l $$ nest 23 v
|
|
| 881 | + fact l v = text l $$ nest 14 v
|
|
| 878 | 882 | |
| 879 | 883 | -- Truncate only pathologically large types
|
| 880 | - pp_ty = sdocWithContext $ \ctx ->
|
|
| 881 | - case splitAt 10000 (showSDocOneLine ctx pp_tidy) of
|
|
| 882 | - (_, []) -> pp_tidy
|
|
| 883 | - (prefix, _) -> text prefix <> text "..."
|
|
| 884 | - where pp_tidy = pprSigmaType (tidyTopType ty)
|
|
| 884 | + pp_ty t = sdocWithContext $ \ctx ->
|
|
| 885 | + case splitAt 10000 (showSDocOneLine ctx pp_tidy) of
|
|
| 886 | + (_, []) -> pp_tidy
|
|
| 887 | + (prefix, _) -> text prefix <> text "..."
|
|
| 888 | + where pp_tidy = pprSigmaType (tidyTopType t)
|
|
| 885 | 889 | -- pprSigmaType: suppress the printed forall
|
| 886 | 890 | |
| 887 | 891 | -- A name with no source span reached this module in an interface
|
| ... | ... | @@ -920,19 +924,25 @@ specConstrProgram guts |
| 920 | 924 | |
| 921 | 925 | pp_pats = vcat (map pp_pat (sortBy cmpReboxedPat pats))
|
| 922 | 926 | |
| 923 | - pp_pat (ReboxedPat shapes cons)
|
|
| 924 | - = hang (hang (ppr fn) 2 (fsep (map pprPatShape shapes))) 2
|
|
| 925 | - (text "-- reboxes" <+>
|
|
| 926 | - pprWithCommas pp_con (sortBy stableNameCmp cons))
|
|
| 927 | + -- "-- reboxes" and "-- as" have equal width, aligning the
|
|
| 928 | + -- payloads; a wrapping signature continues under the type's start
|
|
| 929 | + pp_pat (ReboxedPat shapes cons spec_occ spec_ty)
|
|
| 930 | + = hang (hang (ppr fn) 2 (fsep (map pprPatShape shapes))) 2 $ vcat
|
|
| 931 | + [ text "-- reboxes" <+>
|
|
| 932 | + pprWithCommas pp_con (sortBy stableNameCmp cons)
|
|
| 933 | + , text "-- as" <+>
|
|
| 934 | + quotes (ppr spec_occ <+> dcolon <+> pp_ty spec_ty) ]
|
|
| 927 | 935 | |
| 928 | 936 | -- Qualify imported constructors: they identify the package to
|
| 929 | - -- follow up with when the function itself has no location
|
|
| 937 | + -- follow up with when the function itself has no location.
|
|
| 938 | + -- OccName only: the ambient qual policy may qualify 'ppr con' too,
|
|
| 939 | + -- doubling the prefix
|
|
| 930 | 940 | pp_con con
|
| 931 | 941 | | Just m <- nameModule_maybe con, m /= mg_module guts
|
| 932 | - = quotes (ppr m <> dot <> ppr con)
|
|
| 942 | + = quotes (ppr m <> dot <> ppr (getOccName con))
|
|
| 933 | 943 | | otherwise = quotes (ppr con)
|
| 934 | 944 | |
| 935 | - all_cons = nub [ con | ReboxedPat _ cons <- pats, con <- cons ]
|
|
| 945 | + all_cons = nub [ con | ReboxedPat _ cons _ _ <- pats, con <- cons ]
|
|
| 936 | 946 | |
| 937 | 947 | pp_trailer = fsep $ map text $ words $ case all_cons of
|
| 938 | 948 | [_] -> "This constructor argument is also used boxed, so the specialisation may increase allocation and defeat pointer-equality-based sharing."
|
| ... | ... | @@ -1583,15 +1593,40 @@ that decision bites, without changing which specialisations are made: |
| 1583 | 1593 | -Wspec-constr-reboxing (off by default).
|
| 1584 | 1594 | |
| 1585 | 1595 | * One warning per function, listing each call pattern the function was
|
| 1586 | - specialised for — the constructor skeletons of the call's arguments,
|
|
| 1587 | - e.g. `go (_ : _) (BMap _) -- reboxes ‘BMap’` — alongside that
|
|
| 1588 | - pattern's reboxed constructors. The shapes show where in the
|
|
| 1589 | - argument each reboxed constructor sits, and picture what SpecConstr
|
|
| 1590 | - did: it made a copy of
|
|
| 1596 | + specialised for — the constructor skeletons of the call's arguments —
|
|
| 1597 | + together with that pattern's reboxed constructors and the signature of
|
|
| 1598 | + the specialisation made for it:
|
|
| 1599 | + |
|
| 1600 | + call patterns:
|
|
| 1601 | + go (_ : _) (BMap _)
|
|
| 1602 | + -- reboxes ‘BMap’
|
|
| 1603 | + -- as ‘$sgo :: Int -> Map Int Bool -> Bool’
|
|
| 1604 | + |
|
| 1605 | + The shapes show where in the argument each reboxed constructor sits,
|
|
| 1606 | + and picture what SpecConstr did: it made a copy of
|
|
| 1591 | 1607 | the function for calls of exactly that shape. The warning also shows
|
| 1592 | 1608 | the function's type: names like `go1` say nothing, and for span-less
|
| 1593 | 1609 | functions (last bullet below) the type is the main identifying clue.
|
| 1594 | 1610 | |
| 1611 | +* The spec signature lets the reader find the specialisation in a Core
|
|
| 1612 | + dump and assess the reboxing there. (The "SC:" RULEs are no pointer:
|
|
| 1613 | + they are attached to the *original* binder, and for a local original —
|
|
| 1614 | + the common inlined-library-loop case — Core Tidy drops them.) Both
|
|
| 1615 | + parts of the signature are approximate:
|
|
| 1616 | + |
|
| 1617 | + - The name is the spec's occurrence name at creation ($s<fn>); tidying
|
|
| 1618 | + can prefix the parent and suffix a digit (`$sgo` may end up as
|
|
| 1619 | + `go_$sgo1`), so it is a substring of the final name.
|
|
| 1620 | + |
|
| 1621 | + - The type is the spec binder's type at creation. It normally survives
|
|
| 1622 | + to the final program — the default pipeline runs no worker/wrapper
|
|
| 1623 | + after SpecConstr — but under -flate-dmd-anal the spec can reappear as
|
|
| 1624 | + a `$w$s<fn>` worker with a different type.
|
|
| 1625 | + |
|
| 1626 | + - A listed spec can still be inlined or CSE'd away, and the specs for
|
|
| 1627 | + different patterns can collapse into one, so the signatures are
|
|
| 1628 | + advice, not a 1-1 contract with the final program.
|
|
| 1629 | + |
|
| 1595 | 1630 | "Per function" means per (parent, function) *pair*: the function's
|
| 1596 | 1631 | Name alone is ambiguous, because distinct top-level bindings can bind
|
| 1597 | 1632 | distinct locals that share a unique. That happens when several
|
| ... | ... | @@ -2217,12 +2252,6 @@ specialise env recur bind_calls (RI { ri_fn = fn, ri_lam_bndrs = arg_bndrs |
| 2217 | 2252 | <- callsToNewPats env fn spec_info arg_occs all_calls
|
| 2218 | 2253 | |
| 2219 | 2254 | ; let n_pats = length new_pats
|
| 2220 | - -- Warn about committed specialisations that will rebox;
|
|
| 2221 | - -- see Note [Reboxing warning]
|
|
| 2222 | - rebox_ws = [ SpecReboxed (idName fn) (idType fn) (sc_top_fn env)
|
|
| 2223 | - recur [ReboxedPat (patShapes p) (cp_rebox p)]
|
|
| 2224 | - (cp_callers p)
|
|
| 2225 | - | p <- new_pats, not (null (cp_rebox p)) ]
|
|
| 2226 | 2255 | -- ; when (not (null new_pats) || isJust mb_unspec) $
|
| 2227 | 2256 | -- pprTraceM "specialise" (vcat [ ppr fn <+> text "with" <+> int n_pats <+> text "good patterns"
|
| 2228 | 2257 | -- , text "boring_call:" <+> ppr boring_call
|
| ... | ... | @@ -2242,6 +2271,17 @@ specialise env recur bind_calls (RI { ri_fn = fn, ri_lam_bndrs = arg_bndrs |
| 2242 | 2271 | |
| 2243 | 2272 | ; let spec_usg = combineUsages spec_usgs
|
| 2244 | 2273 | |
| 2274 | + -- Warn about committed specialisations that will rebox,
|
|
| 2275 | + -- naming the specialisation just made for each pattern
|
|
| 2276 | + -- (new_specs is 1-1 with new_pats); see Note [Reboxing warning]
|
|
| 2277 | + rebox_ws = [ SpecReboxed (idName fn) (idType fn) (sc_top_fn env)
|
|
| 2278 | + recur
|
|
| 2279 | + [ReboxedPat (patShapes p) (cp_rebox p)
|
|
| 2280 | + (getOccName spec_id) (idType spec_id)]
|
|
| 2281 | + (cp_callers p)
|
|
| 2282 | + | (p, OS { os_id = spec_id }) <- new_pats `zip` new_specs
|
|
| 2283 | + , not (null (cp_rebox p)) ]
|
|
| 2284 | + |
|
| 2245 | 2285 | unspec_rhs_needed = pats_discarded || boring_call || isExportedId fn
|
| 2246 | 2286 | |
| 2247 | 2287 | -- If there were any boring calls among the seeds (= all_calls), then those
|
| ... | ... | @@ -2804,9 +2844,10 @@ instance Outputable CallPat where |
| 2804 | 2844 | , text "cp_callers = " <> ppr callers ])
|
| 2805 | 2845 | |
| 2806 | 2846 | -- | One call pattern as displayed by the reboxing warning: the shapes of
|
| 2807 | --- the pattern's arguments, and the reboxed constructors among them.
|
|
| 2847 | +-- the pattern's arguments, the reboxed constructors among them, and the
|
|
| 2848 | +-- occurrence name and type of the specialisation made for the pattern.
|
|
| 2808 | 2849 | -- See Note [Reboxing warning]
|
| 2809 | -data ReboxedPat = ReboxedPat [PatShape] [Name]
|
|
| 2850 | +data ReboxedPat = ReboxedPat [PatShape] [Name] OccName Type
|
|
| 2810 | 2851 | |
| 2811 | 2852 | -- | The constructor skeleton of one call-pattern argument, as displayed
|
| 2812 | 2853 | -- by the reboxing warning
|
| ... | ... | @@ -2830,10 +2871,12 @@ patShapes (CP { cp_args = args }) = mapMaybe arg_shape args |
| 2830 | 2871 | | otherwise
|
| 2831 | 2872 | = Just ShapeWild
|
| 2832 | 2873 | |
| 2833 | --- | Stable comparison, used both to merge identically-rendering warnings
|
|
| 2834 | --- and to order a warning's patterns deterministically
|
|
| 2874 | +-- | Stable comparison on the shapes and constructors, used to order a
|
|
| 2875 | +-- warning's patterns deterministically. The merge equality additionally
|
|
| 2876 | +-- compares the spec signatures (Type has no stable Ordering); see
|
|
| 2877 | +-- same_pat in specConstrProgram.
|
|
| 2835 | 2878 | cmpReboxedPat :: ReboxedPat -> ReboxedPat -> Ordering
|
| 2836 | -cmpReboxedPat (ReboxedPat ss1 cs1) (ReboxedPat ss2 cs2)
|
|
| 2879 | +cmpReboxedPat (ReboxedPat ss1 cs1 _ _) (ReboxedPat ss2 cs2 _ _)
|
|
| 2837 | 2880 | = cmpListBy cmpShape ss1 ss2
|
| 2838 | 2881 | `mappend` cmpListBy stableNameCmp (sortBy stableNameCmp cs1)
|
| 2839 | 2882 | (sortBy stableNameCmp cs2)
|
| ... | ... | @@ -2902,7 +2945,7 @@ instance Outputable SpecConstrWarning where |
| 2902 | 2945 | ppr (SpecReboxed fn _ty mb_parent _recur pats _callers)
|
| 2903 | 2946 | = ppr fn <+> parens (pprWithCommas ppr dcs) <+> pp_defn
|
| 2904 | 2947 | where
|
| 2905 | - dcs = [ dc | ReboxedPat _ cons <- pats, dc <- cons ]
|
|
| 2948 | + dcs = [ dc | ReboxedPat _ cons _ _ <- pats, dc <- cons ]
|
|
| 2906 | 2949 | -- A local fn often has no useful location; point at its
|
| 2907 | 2950 | -- enclosing top-level binder instead
|
| 2908 | 2951 | pp_defn = case mb_parent of
|
| ... | ... | @@ -532,7 +532,9 @@ of ``-W(no-)*``. |
| 532 | 532 | Possible remedies include excluding the type from SpecConstr with an
|
| 533 | 533 | ``{-# ANN type T NoSpecConstr #-}`` pragma, hiding the constructor from
|
| 534 | 534 | the call-pattern analysis by wrapping the argument in ``GHC.Exts.lazy``
|
| 535 | - at the call site, or :ghc-flag:`-fno-spec-constr`.
|
|
| 535 | + at the call site, lowering :ghc-flag:`-fspec-constr-threshold=⟨n⟩` in
|
|
| 536 | + the affected module below the function's body size, or
|
|
| 537 | + :ghc-flag:`-fno-spec-constr`.
|
|
| 536 | 538 | |
| 537 | 539 | The warning shows the specialised function's type, which is often the
|
| 538 | 540 | clearest clue to its identity when its name carries no meaning,
|
| ... | ... | @@ -545,13 +547,31 @@ of ``-W(no-)*``. |
| 545 | 547 | ``called from:`` — the top-level bindings containing the specialised
|
| 546 | 548 | calls; ``call patterns:`` — the calls the function was specialised
|
| 547 | 549 | for, shown as the constructor skeletons of their arguments, each
|
| 548 | - alongside the constructors that the specialisation reboxes (for
|
|
| 549 | - example ``go (_ : _) (Bin _ _ _) -- reboxes ‘Bin’``). One warning is emitted per
|
|
| 550 | + followed by the constructors that the specialisation reboxes and by
|
|
| 551 | + the name and type the specialisation was created with::
|
|
| 552 | + |
|
| 553 | + call patterns:
|
|
| 554 | + go (_ : _) (Bin _ _ _)
|
|
| 555 | + -- reboxes ‘Bin’
|
|
| 556 | + -- as ‘$sgo :: Int -> Int -> Map Int Bool -> Bool’
|
|
| 557 | + |
|
| 558 | + One warning is emitted per
|
|
| 550 | 559 | specialised function, and warnings that would read identically are
|
| 551 | 560 | merged into one. Specialisations on nullary constructors are not
|
| 552 | 561 | reported, since "reboxing" a nullary constructor simply references
|
| 553 | 562 | its shared static closure.
|
| 554 | 563 | |
| 564 | + The ``as`` signature is a guide for finding the specialisation in a
|
|
| 565 | + Core dump (:ghc-flag:`-ddump-simpl`), for example to judge how much
|
|
| 566 | + reboxing survives optimisation. Later passes may rename the binder —
|
|
| 567 | + typically to ``<parent>_$s<function>``, possibly with a digit appended
|
|
| 568 | + — so search for the shown name as a substring; the type normally
|
|
| 569 | + survives unchanged. A specialisation can also be inlined, or merged
|
|
| 570 | + with another one, and then appears in no dump. The calls rewritten to
|
|
| 571 | + use specialisations can be traced with
|
|
| 572 | + :ghc-flag:`-ddump-rule-firings`; the rewrite rules are named
|
|
| 573 | + ``SC:<function><n>``.
|
|
| 574 | + |
|
| 555 | 575 | A ``source:`` reading ``inlined from another module (no source
|
| 556 | 576 | location)`` concerns a function that reached the module being compiled
|
| 557 | 577 | through another module's unfolding; interface files record no source
|
| ... | ... | @@ -4,11 +4,18 @@ T27628.hs: warning: [-Wspec-constr-reboxing] |
| 4 | 4 | -> GHC.Internal.Prim.Int#
|
| 5 | 5 | -> GHC.Internal.Prim.Int#
|
| 6 | 6 | -> GHC.Internal.Prim.Int#’
|
| 7 | - source: T27628.hs:17:1
|
|
| 8 | - recursivity: self-recursive
|
|
| 9 | - called from: ‘f’
|
|
| 10 | - call pattern: $wgo (LC _ _) -- reboxes ‘LC’
|
|
| 7 | + source: T27628.hs:17:1
|
|
| 8 | + recursivity: self-recursive
|
|
| 9 | + called from: ‘f’
|
|
| 10 | + call pattern:
|
|
| 11 | + $wgo (LC _ _)
|
|
| 12 | + -- reboxes ‘LC’
|
|
| 13 | + -- as ‘$s$wgo :: Int
|
|
| 14 | + -> Int
|
|
| 15 | + -> GHC.Internal.Prim.Int#
|
|
| 16 | + -> GHC.Internal.Prim.Int#
|
|
| 17 | + -> GHC.Internal.Prim.Int#’
|
|
| 11 | 18 | This constructor argument is also used boxed, so the specialisation
|
| 12 | 19 | may increase allocation and defeat pointer-equality-based sharing.
|
| 13 | - See -Wspec-constr-reboxing in the users guide for possible remedies.
|
|
| 20 | + See -Wspec-constr-reboxing in the user's guide for possible remedies.
|
|
| 14 | 21 |
| 1 | 1 | T27628b.hs: warning: [-Wspec-constr-reboxing]
|
| 2 | 2 | SpecConstr specialised ‘merge :: T -> T -> T’
|
| 3 | - source: T27628b.hs:10:1
|
|
| 4 | - recursivity: self-recursive
|
|
| 5 | - called from: ‘f’
|
|
| 6 | - call pattern: merge (Bin _ _ _) -- reboxes ‘Bin’
|
|
| 3 | + source: T27628b.hs:10:1
|
|
| 4 | + recursivity: self-recursive
|
|
| 5 | + called from: ‘f’
|
|
| 6 | + call pattern:
|
|
| 7 | + merge (Bin _ _ _)
|
|
| 8 | + -- reboxes ‘Bin’
|
|
| 9 | + -- as ‘$smerge :: Int -> T -> T -> T -> T’
|
|
| 7 | 10 | This constructor argument is also used boxed, so the specialisation
|
| 8 | 11 | may increase allocation and defeat pointer-equality-based sharing.
|
| 9 | - See -Wspec-constr-reboxing in the users guide for possible remedies.
|
|
| 12 | + See -Wspec-constr-reboxing in the user's guide for possible remedies.
|
|
| 10 | 13 |
| 1 | 1 | T27628f.hs: warning: [-Wspec-constr-reboxing]
|
| 2 | 2 | SpecConstr specialised ‘merge :: T -> T -> T’
|
| 3 | - source: ‘f’ at T27628f.hs:12:5
|
|
| 4 | - recursivity: self-recursive
|
|
| 5 | - called from: ‘f’
|
|
| 6 | - call pattern: merge (Bin _ _ _) -- reboxes ‘Bin’
|
|
| 3 | + source: ‘f’ at T27628f.hs:12:5
|
|
| 4 | + recursivity: self-recursive
|
|
| 5 | + called from: ‘f’
|
|
| 6 | + call pattern:
|
|
| 7 | + merge (Bin _ _ _)
|
|
| 8 | + -- reboxes ‘Bin’
|
|
| 9 | + -- as ‘$smerge :: Int -> T -> T -> T -> T’
|
|
| 7 | 10 | This constructor argument is also used boxed, so the specialisation
|
| 8 | 11 | may increase allocation and defeat pointer-equality-based sharing.
|
| 9 | - See -Wspec-constr-reboxing in the users guide for possible remedies.
|
|
| 12 | + See -Wspec-constr-reboxing in the user's guide for possible remedies.
|
|
| 10 | 13 |
| 1 | 1 | T27628g.hs: warning: [-Wspec-constr-reboxing]
|
| 2 | 2 | SpecConstr specialised ‘poly_merge :: T a -> T a -> T a’
|
| 3 | - source: T27628g.hs:11:5
|
|
| 4 | - recursivity: self-recursive
|
|
| 5 | - called from: ‘f’
|
|
| 6 | - call pattern: poly_merge (Bin _ _ _) -- reboxes ‘Bin’
|
|
| 3 | + source: T27628g.hs:11:5
|
|
| 4 | + recursivity: self-recursive
|
|
| 5 | + called from: ‘f’
|
|
| 6 | + call pattern:
|
|
| 7 | + poly_merge (Bin _ _ _)
|
|
| 8 | + -- reboxes ‘Bin’
|
|
| 9 | + -- as ‘$spoly_merge :: a -> T a -> T a -> T a -> T a’
|
|
| 7 | 10 | This constructor argument is also used boxed, so the specialisation
|
| 8 | 11 | may increase allocation and defeat pointer-equality-based sharing.
|
| 9 | - See -Wspec-constr-reboxing in the users guide for possible remedies.
|
|
| 12 | + See -Wspec-constr-reboxing in the user's guide for possible remedies.
|
|
| 10 | 13 |
| 1 | 1 | ./T27628h_M.hs: warning: [-Wspec-constr-reboxing]
|
| 2 | 2 | SpecConstr specialised ‘poly_merge :: T a -> T a -> T a’
|
| 3 | - source: T27628h_M.hs:11:5
|
|
| 4 | - recursivity: self-recursive
|
|
| 5 | - called from: ‘f’
|
|
| 6 | - call pattern: poly_merge (Bin _ _ _) -- reboxes ‘Bin’
|
|
| 3 | + source: T27628h_M.hs:11:5
|
|
| 4 | + recursivity: self-recursive
|
|
| 5 | + called from: ‘f’
|
|
| 6 | + call pattern:
|
|
| 7 | + poly_merge (Bin _ _ _)
|
|
| 8 | + -- reboxes ‘Bin’
|
|
| 9 | + -- as ‘$spoly_merge :: a -> T a -> T a -> T a -> T a’
|
|
| 7 | 10 | This constructor argument is also used boxed, so the specialisation
|
| 8 | 11 | may increase allocation and defeat pointer-equality-based sharing.
|
| 9 | - See -Wspec-constr-reboxing in the users guide for possible remedies.
|
|
| 12 | + See -Wspec-constr-reboxing in the user's guide for possible remedies.
|
|
| 10 | 13 | |
| 11 | 14 | T27628h.hs: warning: [-Wspec-constr-reboxing]
|
| 12 | 15 | SpecConstr specialised ‘merge :: T Int -> T Int -> T Int’
|
| 13 | - source: inlined from another module (no source location)
|
|
| 14 | - recursivity: self-recursive
|
|
| 15 | - called from: ‘g’
|
|
| 16 | - call pattern: merge (Bin _ _ _) -- reboxes ‘T27628h_M.Bin’
|
|
| 16 | + source: inlined from another module (no source location)
|
|
| 17 | + recursivity: self-recursive
|
|
| 18 | + called from: ‘g’
|
|
| 19 | + call pattern:
|
|
| 20 | + merge (Bin _ _ _)
|
|
| 21 | + -- reboxes ‘T27628h_M.Bin’
|
|
| 22 | + -- as ‘$smerge :: Int -> T Int -> T Int -> T Int -> T Int’
|
|
| 17 | 23 | This constructor argument is also used boxed, so the specialisation
|
| 18 | 24 | may increase allocation and defeat pointer-equality-based sharing.
|
| 19 | - See -Wspec-constr-reboxing in the users guide for possible remedies.
|
|
| 25 | + See -Wspec-constr-reboxing in the user's guide for possible remedies.
|
|
| 20 | 26 |
| 1 | 1 | ./T27628i_M.hs: warning: [-Wspec-constr-reboxing]
|
| 2 | 2 | SpecConstr specialised ‘poly_merge :: T a -> T a -> T a’
|
| 3 | - source: T27628i_M.hs:36:5
|
|
| 4 | - recursivity: self-recursive
|
|
| 5 | - called from: ‘f3’
|
|
| 6 | - call pattern: poly_merge (Bin _ _ _) -- reboxes ‘Bin’
|
|
| 3 | + source: T27628i_M.hs:36:5
|
|
| 4 | + recursivity: self-recursive
|
|
| 5 | + called from: ‘f3’
|
|
| 6 | + call pattern:
|
|
| 7 | + poly_merge (Bin _ _ _)
|
|
| 8 | + -- reboxes ‘Bin’
|
|
| 9 | + -- as ‘$spoly_merge :: a -> T a -> T a -> T a -> T a’
|
|
| 7 | 10 | This constructor argument is also used boxed, so the specialisation
|
| 8 | 11 | may increase allocation and defeat pointer-equality-based sharing.
|
| 9 | - See -Wspec-constr-reboxing in the users guide for possible remedies.
|
|
| 12 | + See -Wspec-constr-reboxing in the user's guide for possible remedies.
|
|
| 10 | 13 | |
| 11 | 14 | ./T27628i_M.hs: warning: [-Wspec-constr-reboxing]
|
| 12 | 15 | SpecConstr specialised ‘poly_merge :: S a -> S a -> S a’
|
| 13 | - source: T27628i_M.hs:24:5
|
|
| 14 | - recursivity: self-recursive
|
|
| 15 | - called from: ‘f2’
|
|
| 16 | - call pattern: poly_merge (Node _ _ _) -- reboxes ‘Node’
|
|
| 16 | + source: T27628i_M.hs:24:5
|
|
| 17 | + recursivity: self-recursive
|
|
| 18 | + called from: ‘f2’
|
|
| 19 | + call pattern:
|
|
| 20 | + poly_merge (Node _ _ _)
|
|
| 21 | + -- reboxes ‘Node’
|
|
| 22 | + -- as ‘$spoly_merge :: a -> S a -> S a -> S a -> S a’
|
|
| 17 | 23 | This constructor argument is also used boxed, so the specialisation
|
| 18 | 24 | may increase allocation and defeat pointer-equality-based sharing.
|
| 19 | - See -Wspec-constr-reboxing in the users guide for possible remedies.
|
|
| 25 | + See -Wspec-constr-reboxing in the user's guide for possible remedies.
|
|
| 20 | 26 | |
| 21 | 27 | ./T27628i_M.hs: warning: [-Wspec-constr-reboxing]
|
| 22 | 28 | SpecConstr specialised ‘poly_merge :: T a -> T a -> T a’
|
| 23 | - source: T27628i_M.hs:14:5
|
|
| 24 | - recursivity: self-recursive
|
|
| 25 | - called from: ‘f1’
|
|
| 26 | - call pattern: poly_merge (Bin _ _ _) -- reboxes ‘Bin’
|
|
| 29 | + source: T27628i_M.hs:14:5
|
|
| 30 | + recursivity: self-recursive
|
|
| 31 | + called from: ‘f1’
|
|
| 32 | + call pattern:
|
|
| 33 | + poly_merge (Bin _ _ _)
|
|
| 34 | + -- reboxes ‘Bin’
|
|
| 35 | + -- as ‘$spoly_merge :: a -> T a -> T a -> T a -> T a’
|
|
| 27 | 36 | This constructor argument is also used boxed, so the specialisation
|
| 28 | 37 | may increase allocation and defeat pointer-equality-based sharing.
|
| 29 | - See -Wspec-constr-reboxing in the users guide for possible remedies.
|
|
| 38 | + See -Wspec-constr-reboxing in the user's guide for possible remedies.
|
|
| 30 | 39 | |
| 31 | 40 | T27628i.hs: warning: [-Wspec-constr-reboxing]
|
| 32 | 41 | SpecConstr specialised ‘merge :: T Int -> T Int -> T Int’
|
| 33 | - source: inlined from another module (no source location)
|
|
| 34 | - recursivity: self-recursive
|
|
| 35 | - called from: ‘g1’, ‘g3’
|
|
| 36 | - call pattern: merge (Bin _ _ _) -- reboxes ‘T27628i_M.Bin’
|
|
| 42 | + source: inlined from another module (no source location)
|
|
| 43 | + recursivity: self-recursive
|
|
| 44 | + called from: ‘g1’, ‘g3’
|
|
| 45 | + call pattern:
|
|
| 46 | + merge (Bin _ _ _)
|
|
| 47 | + -- reboxes ‘T27628i_M.Bin’
|
|
| 48 | + -- as ‘$smerge :: Int -> T Int -> T Int -> T Int -> T Int’
|
|
| 37 | 49 | This constructor argument is also used boxed, so the specialisation
|
| 38 | 50 | may increase allocation and defeat pointer-equality-based sharing.
|
| 39 | - See -Wspec-constr-reboxing in the users guide for possible remedies.
|
|
| 51 | + See -Wspec-constr-reboxing in the user's guide for possible remedies.
|
|
| 40 | 52 | |
| 41 | 53 | T27628i.hs: warning: [-Wspec-constr-reboxing]
|
| 42 | 54 | SpecConstr specialised ‘merge :: S Int -> S Int -> S Int’
|
| 43 | - source: inlined from another module (no source location)
|
|
| 44 | - recursivity: self-recursive
|
|
| 45 | - called from: ‘g2’
|
|
| 46 | - call pattern: merge (Node _ _ _)
|
|
| 47 | - -- reboxes ‘T27628i_M.Node’
|
|
| 55 | + source: inlined from another module (no source location)
|
|
| 56 | + recursivity: self-recursive
|
|
| 57 | + called from: ‘g2’
|
|
| 58 | + call pattern:
|
|
| 59 | + merge (Node _ _ _)
|
|
| 60 | + -- reboxes ‘T27628i_M.Node’
|
|
| 61 | + -- as ‘$smerge :: Int -> S Int -> S Int -> S Int -> S Int’
|
|
| 48 | 62 | This constructor argument is also used boxed, so the specialisation
|
| 49 | 63 | may increase allocation and defeat pointer-equality-based sharing.
|
| 50 | - See -Wspec-constr-reboxing in the users guide for possible remedies.
|
|
| 64 | + See -Wspec-constr-reboxing in the user's guide for possible remedies.
|
|
| 51 | 65 |
| 1 | 1 | T27628j.hs: warning: [-Wspec-constr-reboxing]
|
| 2 | 2 | SpecConstr specialised ‘mergeB :: T -> T -> T’
|
| 3 | - source: T27628j.hs:17:1
|
|
| 4 | - recursivity: mutually recursive with ‘mergeA’
|
|
| 5 | - called from: ‘g’
|
|
| 6 | - call pattern: mergeB (Bin _ _ _) -- reboxes ‘Bin’
|
|
| 3 | + source: T27628j.hs:17:1
|
|
| 4 | + recursivity: mutually recursive with ‘mergeA’
|
|
| 5 | + called from: ‘g’
|
|
| 6 | + call pattern:
|
|
| 7 | + mergeB (Bin _ _ _)
|
|
| 8 | + -- reboxes ‘Bin’
|
|
| 9 | + -- as ‘$smergeB :: Int -> T -> T -> T -> T’
|
|
| 7 | 10 | This constructor argument is also used boxed, so the specialisation
|
| 8 | 11 | may increase allocation and defeat pointer-equality-based sharing.
|
| 9 | - See -Wspec-constr-reboxing in the users guide for possible remedies.
|
|
| 12 | + See -Wspec-constr-reboxing in the user's guide for possible remedies.
|
|
| 10 | 13 |
| 1 | 1 | T27628k.hs: warning: [-Wspec-constr-reboxing]
|
| 2 | 2 | SpecConstr specialised ‘go :: T -> Int -> Int’
|
| 3 | - source: T27628k.hs:17:1
|
|
| 4 | - recursivity: self-recursive
|
|
| 5 | - call patterns: go (A _) (I# _) -- reboxes ‘A’
|
|
| 6 | - go (B _) (I# _) -- reboxes ‘B’
|
|
| 3 | + source: T27628k.hs:17:1
|
|
| 4 | + recursivity: self-recursive
|
|
| 5 | + call patterns:
|
|
| 6 | + go (A _) (I# _)
|
|
| 7 | + -- reboxes ‘A’
|
|
| 8 | + -- as ‘$sgo :: Int -> GHC.Internal.Prim.Int# -> Int’
|
|
| 9 | + go (B _) (I# _)
|
|
| 10 | + -- reboxes ‘B’
|
|
| 11 | + -- as ‘$sgo :: Int -> GHC.Internal.Prim.Int# -> Int’
|
|
| 7 | 12 | These constructor arguments are also used boxed, so the
|
| 8 | 13 | specialisations may increase allocation and defeat
|
| 9 | 14 | pointer-equality-based sharing.
|
| 10 | - See -Wspec-constr-reboxing in the users guide for possible remedies.
|
|
| 15 | + See -Wspec-constr-reboxing in the user's guide for possible remedies.
|
|
| 11 | 16 |
| 1 | 1 | T27628l.hs: warning: [-Wspec-constr-reboxing]
|
| 2 | 2 | SpecConstr specialised ‘go1 :: [Max a] -> Max a -> Max a’
|
| 3 | - source: ‘$cmconcat’ at T27628l.hs:22:5
|
|
| 4 | - recursivity: self-recursive
|
|
| 5 | - called from: ‘$cmconcat’
|
|
| 6 | - call pattern: go1 _ (Just _)
|
|
| 7 | - -- reboxes ‘GHC.Internal.Maybe.Just’
|
|
| 3 | + source: ‘$cmconcat’ at T27628l.hs:22:5
|
|
| 4 | + recursivity: self-recursive
|
|
| 5 | + called from: ‘$cmconcat’
|
|
| 6 | + call pattern:
|
|
| 7 | + go1 _ (Just _)
|
|
| 8 | + -- reboxes ‘GHC.Internal.Maybe.Just’
|
|
| 9 | + -- as ‘$sgo1 :: [Max a] -> a -> Max a’
|
|
| 8 | 10 | This constructor argument is also used boxed, so the specialisation
|
| 9 | 11 | may increase allocation and defeat pointer-equality-based sharing.
|
| 10 | - See -Wspec-constr-reboxing in the users guide for possible remedies.
|
|
| 12 | + See -Wspec-constr-reboxing in the user's guide for possible remedies.
|
|
| 11 | 13 | |
| 12 | 14 | T27628l.hs: warning: [-Wspec-constr-reboxing]
|
| 13 | 15 | SpecConstr specialised ‘exit :: Max a -> b -> Max a’
|
| 14 | - source: ‘$cstimes’ at T27628l.hs:12:10
|
|
| 15 | - recursivity: non-recursive (a join point)
|
|
| 16 | - called from: ‘$cstimes’
|
|
| 17 | - call pattern: exit (Just _) _
|
|
| 18 | - -- reboxes ‘GHC.Internal.Maybe.Just’
|
|
| 16 | + source: ‘$cstimes’ at T27628l.hs:12:10
|
|
| 17 | + recursivity: non-recursive (a join point)
|
|
| 18 | + called from: ‘$cstimes’
|
|
| 19 | + call pattern:
|
|
| 20 | + exit (Just _) _
|
|
| 21 | + -- reboxes ‘GHC.Internal.Maybe.Just’
|
|
| 22 | + -- as ‘$sexit :: a -> b -> Max a’
|
|
| 19 | 23 | This constructor argument is also used boxed, so the specialisation
|
| 20 | 24 | may increase allocation and defeat pointer-equality-based sharing.
|
| 21 | - See -Wspec-constr-reboxing in the users guide for possible remedies.
|
|
| 25 | + See -Wspec-constr-reboxing in the user's guide for possible remedies.
|
|
| 22 | 26 | |
| 23 | 27 | T27628l.hs: warning: [-Wspec-constr-reboxing]
|
| 24 | 28 | SpecConstr specialised ‘g :: Max a -> b -> Max a -> Max a’
|
| 25 | - source: ‘$cstimes’ at T27628l.hs:12:10
|
|
| 26 | - recursivity: self-recursive
|
|
| 27 | - called from: ‘$cstimes’
|
|
| 28 | - call pattern: g (Just _) _ _
|
|
| 29 | - -- reboxes ‘GHC.Internal.Maybe.Just’
|
|
| 29 | + source: ‘$cstimes’ at T27628l.hs:12:10
|
|
| 30 | + recursivity: self-recursive
|
|
| 31 | + called from: ‘$cstimes’
|
|
| 32 | + call pattern:
|
|
| 33 | + g (Just _) _ _
|
|
| 34 | + -- reboxes ‘GHC.Internal.Maybe.Just’
|
|
| 35 | + -- as ‘$sg :: a -> b -> Max a -> Max a’
|
|
| 30 | 36 | This constructor argument is also used boxed, so the specialisation
|
| 31 | 37 | may increase allocation and defeat pointer-equality-based sharing.
|
| 32 | - See -Wspec-constr-reboxing in the users guide for possible remedies.
|
|
| 38 | + See -Wspec-constr-reboxing in the user's guide for possible remedies.
|
|
| 33 | 39 | |
| 34 | 40 | T27628l.hs: warning: [-Wspec-constr-reboxing]
|
| 35 | 41 | SpecConstr specialised ‘go1 :: [Min a] -> Min a -> Min a’
|
| 36 | - source: ‘$cmconcat’ at T27628l.hs:37:5
|
|
| 37 | - recursivity: self-recursive
|
|
| 38 | - called from: ‘$cmconcat’
|
|
| 39 | - call pattern: go1 _ (Just _)
|
|
| 40 | - -- reboxes ‘GHC.Internal.Maybe.Just’
|
|
| 42 | + source: ‘$cmconcat’ at T27628l.hs:37:5
|
|
| 43 | + recursivity: self-recursive
|
|
| 44 | + called from: ‘$cmconcat’
|
|
| 45 | + call pattern:
|
|
| 46 | + go1 _ (Just _)
|
|
| 47 | + -- reboxes ‘GHC.Internal.Maybe.Just’
|
|
| 48 | + -- as ‘$sgo1 :: [Min a] -> a -> Min a’
|
|
| 41 | 49 | This constructor argument is also used boxed, so the specialisation
|
| 42 | 50 | may increase allocation and defeat pointer-equality-based sharing.
|
| 43 | - See -Wspec-constr-reboxing in the users guide for possible remedies.
|
|
| 51 | + See -Wspec-constr-reboxing in the user's guide for possible remedies.
|
|
| 44 | 52 | |
| 45 | 53 | T27628l.hs: warning: [-Wspec-constr-reboxing]
|
| 46 | 54 | SpecConstr specialised ‘exit :: Min a -> b -> Min a’
|
| 47 | - source: ‘$cstimes’ at T27628l.hs:27:10
|
|
| 48 | - recursivity: non-recursive (a join point)
|
|
| 49 | - called from: ‘$cstimes’
|
|
| 50 | - call pattern: exit (Just _) _
|
|
| 51 | - -- reboxes ‘GHC.Internal.Maybe.Just’
|
|
| 55 | + source: ‘$cstimes’ at T27628l.hs:27:10
|
|
| 56 | + recursivity: non-recursive (a join point)
|
|
| 57 | + called from: ‘$cstimes’
|
|
| 58 | + call pattern:
|
|
| 59 | + exit (Just _) _
|
|
| 60 | + -- reboxes ‘GHC.Internal.Maybe.Just’
|
|
| 61 | + -- as ‘$sexit :: a -> b -> Min a’
|
|
| 52 | 62 | This constructor argument is also used boxed, so the specialisation
|
| 53 | 63 | may increase allocation and defeat pointer-equality-based sharing.
|
| 54 | - See -Wspec-constr-reboxing in the users guide for possible remedies.
|
|
| 64 | + See -Wspec-constr-reboxing in the user's guide for possible remedies.
|
|
| 55 | 65 | |
| 56 | 66 | T27628l.hs: warning: [-Wspec-constr-reboxing]
|
| 57 | 67 | SpecConstr specialised ‘g :: Min a -> b -> Min a -> Min a’
|
| 58 | - source: ‘$cstimes’ at T27628l.hs:27:10
|
|
| 59 | - recursivity: self-recursive
|
|
| 60 | - called from: ‘$cstimes’
|
|
| 61 | - call pattern: g (Just _) _ _
|
|
| 62 | - -- reboxes ‘GHC.Internal.Maybe.Just’
|
|
| 68 | + source: ‘$cstimes’ at T27628l.hs:27:10
|
|
| 69 | + recursivity: self-recursive
|
|
| 70 | + called from: ‘$cstimes’
|
|
| 71 | + call pattern:
|
|
| 72 | + g (Just _) _ _
|
|
| 73 | + -- reboxes ‘GHC.Internal.Maybe.Just’
|
|
| 74 | + -- as ‘$sg :: a -> b -> Min a -> Min a’
|
|
| 63 | 75 | This constructor argument is also used boxed, so the specialisation
|
| 64 | 76 | may increase allocation and defeat pointer-equality-based sharing.
|
| 65 | - See -Wspec-constr-reboxing in the users guide for possible remedies.
|
|
| 77 | + See -Wspec-constr-reboxing in the user's guide for possible remedies.
|
|
| 66 | 78 |
| 1 | +-- Like T27628h, but the constructor is in scope only qualified (M.Bin),
|
|
| 2 | +-- so the ambient qual policy qualifies it in the warning. The warning's
|
|
| 3 | +-- own module prefix must not stack on top: expect ‘T27628h_M.Bin’, not
|
|
| 4 | +-- ‘T27628h_M.M.Bin’.
|
|
| 5 | +module T27628m where
|
|
| 6 | + |
|
| 7 | +import qualified T27628h_M as M
|
|
| 8 | + |
|
| 9 | +g :: Int -> M.T Int -> M.T Int
|
|
| 10 | +g x t = M.f x (M.f x t) |
| 1 | +./T27628h_M.hs: warning: [-Wspec-constr-reboxing]
|
|
| 2 | + SpecConstr specialised ‘poly_merge :: T a -> T a -> T a’
|
|
| 3 | + source: T27628h_M.hs:11:5
|
|
| 4 | + recursivity: self-recursive
|
|
| 5 | + called from: ‘f’
|
|
| 6 | + call pattern:
|
|
| 7 | + poly_merge (Bin _ _ _)
|
|
| 8 | + -- reboxes ‘Bin’
|
|
| 9 | + -- as ‘$spoly_merge :: a -> T a -> T a -> T a -> T a’
|
|
| 10 | + This constructor argument is also used boxed, so the specialisation
|
|
| 11 | + may increase allocation and defeat pointer-equality-based sharing.
|
|
| 12 | + See -Wspec-constr-reboxing in the user's guide for possible remedies.
|
|
| 13 | + |
|
| 14 | +T27628m.hs: warning: [-Wspec-constr-reboxing]
|
|
| 15 | + SpecConstr specialised ‘merge :: M.T Int -> M.T Int -> M.T Int’
|
|
| 16 | + source: inlined from another module (no source location)
|
|
| 17 | + recursivity: self-recursive
|
|
| 18 | + called from: ‘g’
|
|
| 19 | + call pattern:
|
|
| 20 | + merge (Bin _ _ _)
|
|
| 21 | + -- reboxes ‘T27628h_M.Bin’
|
|
| 22 | + -- as ‘$smerge :: Int
|
|
| 23 | + -> M.T Int -> M.T Int -> M.T Int -> M.T Int’
|
|
| 24 | + This constructor argument is also used boxed, so the specialisation
|
|
| 25 | + may increase allocation and defeat pointer-equality-based sharing.
|
|
| 26 | + See -Wspec-constr-reboxing in the user's guide for possible remedies. |
| ... | ... | @@ -625,3 +625,4 @@ test('T27628i', [extra_files(['T27628i_M.hs'])], multimod_compile, ['T27628i', ' |
| 625 | 625 | test('T27628j', normal, compile, ['-O2 -Wspec-constr-reboxing'])
|
| 626 | 626 | test('T27628k', normal, compile, ['-O2 -Wspec-constr-reboxing'])
|
| 627 | 627 | test('T27628l', normal, compile, ['-O2 -Wspec-constr-reboxing -dsuppress-uniques'])
|
| 628 | +test('T27628m', [extra_files(['T27628h_M.hs'])], multimod_compile, ['T27628m', '-v0 -O2 -Wspec-constr-reboxing -dsuppress-uniques']) |