[Git][ghc/ghc][wip/T23070-dicts] Documentation changes only
Simon Peyton Jones (@simonpj)
gitlab at gitlab.haskell.org
Thu May 18 16:46:03 UTC 2023
Simon Peyton Jones pushed to branch wip/T23070-dicts at Glasgow Haskell Compiler / GHC
Commits:
84258bdc by Simon Peyton Jones at 2023-05-18T17:47:47+01:00
Documentation changes only
- - - - -
2 changed files:
- compiler/GHC/Tc/Errors/Hole.hs
- compiler/GHC/Tc/Solver/Dict.hs
Changes:
=====================================
compiler/GHC/Tc/Errors/Hole.hs
=====================================
@@ -989,7 +989,7 @@ tcCheckHoleFit (TypedHole {..}) hole_ty ty = discardErrs $
-> do { traceTc "}" empty
; return (True, wrap) }
- | checkInsoluble wanted
+ | checkInsoluble wanted -- See Note [Fast path for tcCheckHoleFit]
-> return (False, wrap)
| otherwise
@@ -1001,7 +1001,7 @@ tcCheckHoleFit (TypedHole {..}) hole_ty ty = discardErrs $
-- Note [Checking hole fits]
; let wrapInImpls cts = foldl (flip (setWCAndBinds fresh_binds)) cts th_implics
final_wc = wrapInImpls $ addSimples wanted $
- mapBag mkNonCanonical cloned_relevants
+ mapBag mkNonCanonical cloned_relevants
-- We add the cloned relevants to the wanteds generated
-- by the call to tcSubType_NC, for details, see
-- Note [Relevant constraints]. There's no need to clone
@@ -1022,7 +1022,26 @@ tcCheckHoleFit (TypedHole {..}) hole_ty ty = discardErrs $
setWCAndBinds binds imp wc
= mkImplicWC $ unitBag $ imp { ic_wanted = wc , ic_binds = binds }
+{- Note [Fast path for tcCheckHoleFit]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+In `tcCheckHoleFit` we compare (with `tcSubTypeSigma`) the type of the hole
+with the type of zillions of in-scope functions, to see which would "fit".
+Most of these checks fail! They generate obviously-insoluble constraints.
+For these very-common cases we don't want to crank up the full constraint
+solver. It's much more efficient to do a quick-and-dirty check for insolubility.
+
+Now, `tcSubTypeSigma` uses the on-the-fly unifier in GHC.Tc.Utils.Unify,
+it has already done the dirt-simple unification. So our quick-and-dirty
+check can simply look for constraints like (Int ~ Bool). We don't need
+to worry about (Maybe Int ~ Maybe Bool).
+
+The quick-and-dirty check is in `checkInsoluble`. It can make a big
+difference: For test hard_hole_fits, compile-time allocation goes down by 37%!
+-}
+
+
checkInsoluble :: WantedConstraints -> Bool
+-- See Note [Fast path for tcCheckHoleFit]
checkInsoluble (WC { wc_simple = simples })
= any is_insol simples
where
@@ -1031,6 +1050,8 @@ checkInsoluble (WC { wc_simple = simples })
_ -> False
definitelyNotEqual :: Role -> TcType -> TcType -> Bool
+-- See Note [Fast path for tcCheckHoleFit]
+-- Specifically, does not need to recurse under type constructors
definitelyNotEqual r t1 t2
= go t1 t2
where
@@ -1048,4 +1069,4 @@ definitelyNotEqual r t1 t2
go_tc tc1 (TyConApp tc2 _) | isGenerativeTyCon tc2 r = tc1 /= tc2
go_tc _ (FunTy {}) = True
go_tc _ (ForAllTy {}) = True
- go_tc _ _ = False
\ No newline at end of file
+ go_tc _ _ = False
=====================================
compiler/GHC/Tc/Solver/Dict.hs
=====================================
@@ -298,6 +298,87 @@ I can think of two ways to fix this:
* *
****************************************************************************** -}
+{- Note [Solving equality classes]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Consider (~), which behaves as if it was defined like this:
+ class a ~# b => a ~ b
+ instance a ~# b => a ~ b
+There are two more similar "equality classes" like this. The full list is
+ * (~) eqTyCon
+ * (~~) heqTyCon
+ * Coercible coercibleTyCon
+(See Note [The equality types story] in GHC.Builtin.Types.Prim.)
+
+(EQC1) For Givens, when expanding the superclasses of a equality class,
+ we can /replace/ the constraint with its superclasses (which, remember, are
+ equally powerful) rather than /adding/ them. This can make a huge difference.
+ Consider T17836, which has a constraint like
+ forall b,c. a ~ (b,c) =>
+ forall d,e. c ~ (d,e) =>
+ ...etc...
+ If we just /add/ the superclasses of [G] g1:a ~ (b,c), we'll put
+ [G] g1:(a~(b,c)) in the inert set and emit [G] g2:a ~# (b,c). That will
+ kick out g1, and it'll be re-inserted as [G] g1':(b,c)~(b,c) which does
+ no good to anyone. When the implication is deeply nested, this has
+ quadratic cost, and no benefit. Just replace!
+
+ (This can have a /big/ effect: test T17836 involves deeply-nested GADT
+ pattern matching. Its compile-time allocation decreased by 40% when
+ I added the "replace" rather than "add" semantics.)
+
+(EQC2) Faced with [W] t1 ~ t2, it's always OK to reduce it to [W] t1 ~# t2,
+ without worrying about Note [Instance and Given overlap]. Why? Because
+ if we had [G] s1 ~ s2, then we'd get the superclass [G] s1 ~# s2, and
+ so the reduction of the [W] constraint does not risk losing any solutions.
+
+ On the other hand, it can be fatal to /fail/ to reduce such equalities
+ on the grounds of Note [Instance and Given overlap], because many good
+ things flow from [W] t1 ~# t2.
+
+Conclusion: we have a special solver pipeline for equality-class constraints,
+`solveEqualityDict`. It aggressively decomposes the boxed equality constraint
+into an unboxed coercion, both for Givens and Wanteds, and /replaces/ the
+boxed equality constraint with the unboxed one, so that the inert set never
+contains the boxed one.
+
+Note [Solving tuple constraints]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+I tried treating tuple constraints, such as (% Eq a, Show a %), rather like
+equality-class constraints (see Note [Solving equality classes]). That is, by
+eagerly decomposing tuple-constraints into their component (Eq a) and (Show a).
+
+But discarding the tuple Given (which "replacing" does) means that
+we may have to reconstruct it for a recursive call, and the optimiser isn't
+quite clever enough to figure that out: see #10359 and its test case; and #23398.
+This is less pressing for equality classes because they have to be unpacked
+strictly, so CSE-ing away the reconstruction works fine.
+
+
+(NC2) Because of this replacement, we don't need do the fancy footwork
+ of Note [Solving superclass constraints], so the computation of `sc_loc`
+ in `mk_strict_superclasses` can be simpler.
+
+ For tuple predicates, this matters, because their size can be large,
+ and we don't want to add a big class to the size of the dictionaries
+ in the chain. When we get down to a base predicate, we'll include
+ its size. See #10335
+
+And less obviously to:
+
+* Tuple classes. For reasons described in GHC.Tc.Solver.Types
+ Note [Shadowing of implicit parameters], we may have a constraint
+ [W] (?x::Int, C a)
+ with an exactly-matching Given constraint. We must decompose this
+ tuple and solve the components separately, otherwise we won't solve
+ it at all! It is perfectly safe to decompose it, because again the
+ superclasses invert the instance; e.g.
+ class (c1, c2) => (% c1, c2 %)
+ instance (c1, c2) => (% c1, c2 %)
+ Example in #14218
+
+Examples: T5853, T10432, T5315, T9222, T2627b, T3028b
+-}
+
solveEqualityDict :: CtEvidence -> Class -> [Type] -> SolverStage Void
-- Precondition: (isEqualityClass cls) True, so cls is (~), (~~), or Coercible
solveEqualityDict ev cls tys
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/84258bdcc5ca417b58aaeb8dc2058b42e3ca0e65
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/84258bdcc5ca417b58aaeb8dc2058b42e3ca0e65
You're receiving this email because of your account on gitlab.haskell.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20230518/3c0f5781/attachment-0001.html>
More information about the ghc-commits
mailing list