Note [Solving superclass constraints]
How do we ensure that every superclass witness in an instance declaration is generated by one of (sc1) (sc2) or (sc3) in Note [Recursive superclasses]? Answer: * The "given" constraints of an instance decl have CtOrigin of (GivenOrigin (InstSkol head_size)), where head_size is the PatersonSize of the head of the instance declaration. E.g. in instance D a => C [a] the `[G] D a` constraint has a CtOrigin whose head_size is the PatersonSize of (C [a]). * When we make a superclass selection from a Given (transitively) we give it a CtOrigin of (GivenSCOrigin skol_info sc_depth blocked). The 'blocked :: Bool' flag says if the superclass can be used to solve a superclass Wanted. The new superclass is blocked unless: it is the superclass of an unblocked dictionary (wrinkle (W1)), that is Paterson-smaller than the instance head. This is implemented in GHC.Tc.Solver.Dict.mk_strict_superclasses (in the mk_given_loc helper function). * Superclass "Wanted" constraints have CtOrigin of (ScOrigin NakedSc) The 'NakedSc' says that this is a naked superclass Wanted; we must be careful when solving it. * (sc1) When we rewrite such a wanted constraint, it retains its origin. But if we apply an instance declaration, we can set the origin to (ScOrigin NotNakedSc), thus lifting any restrictions by making prohibitedSuperClassSolve return False. This happens in GHC.Tc.Solver.Dict.checkInstanceOK. * (sc2) ScOrigin wanted constraints can't be solved from a superclass selection, except at a smaller type. This test is implemented by GHC.Tc.Solver.InertSet.prohibitedSuperClassSolve Note [Silent superclass arguments] (historical interest only) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ NB1: this note describes our *old* solution to the recursive-superclass problem. I'm keeping the Note for now, just as institutional memory. However, the code for silent superclass arguments was removed in late Dec 2014 NB2: the silent-superclass solution introduced new problems of its own, in the form of instance overlap. Tests SilentParametersOverlapping, T5051, and T7862 are examples NB3: the silent-superclass solution also generated tons of extra dictionaries. For example, in monad-transformer code, when constructing a Monad dictionary you had to pass an Applicative dictionary; and to construct that you need a Functor dictionary. Yet these extra dictionaries were often never used. Test T3064 compiled *far* faster after silent superclasses were eliminated. Our solution to this problem "silent superclass arguments". We pass to each dfun some ``silent superclass arguments’’, which are the immediate superclasses of the dictionary we are trying to construct. In our example: dfun :: forall a. C [a] -> D [a] -> D [a] dfun = \(dc::C [a]) (dd::D [a]) -> DOrd dc ... Notice the extra (dc :: C [a]) argument compared to the previous version. This gives us: DFun Superclass Invariant ~~~~~~~~~~~~~~~~~~~~~~~~ In the body of a DFun, every superclass argument to the returned dictionary is either * one of the arguments of the DFun, or * constant, bound at top level This net effect is that it is safe to treat a dfun application as wrapping a dictionary constructor around its arguments (in particular, a dfun never picks superclasses from the arguments under the dictionary constructor). No superclass is hidden inside a dfun application. The extra arguments required to satisfy the DFun Superclass Invariant always come first, and are called the "silent" arguments. You can find out how many silent arguments there are using Id.dfunNSilent; and then you can just drop that number of arguments to see the ones that were in the original instance declaration. DFun types are built (only) by MkId.mkDictFunId, so that is where we decide what silent arguments are to be added.
References 1
- Recursive superclasses GHC.Tc.TyCl.Instance
Referenced by 13
- GHC.Tc.Solver.Dict call site ×4
- GHC.Tc.Solver.InertSet call site ×2
- GHC.Tc.Types.Origin call site ×2
- NON-BOTTOM-DICTS invariant GHC.Core
- Replacement vs keeping GHC.Tc.Solver.InertSet
- Solving a Wanted forall-constraint GHC.Tc.Solver.Solve
- GHC.Tc.TyCl.Instance call site
- GHC.Tc.Utils.TcType call site