[GHC] #15952: Reduce zonking-related invariants in the type checker
GHC
ghc-devs at haskell.org
Sun Dec 30 23:55:06 UTC 2018
#15952: Reduce zonking-related invariants in the type checker
-------------------------------------+-------------------------------------
Reporter: goldfire | Owner: (none)
Type: task | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 8.6.2
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
| Unknown/Multiple
Type of failure: None/Unknown | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s):
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by simonpj):
I have made some progress here, all on `wip/T15952`.
A big goal is to sweep away two tricky invariants:
* `Note [The well-kinded type invariant]` in `TcType`, which asked that
`tcTypeKind` would work even before zonking. But that led to the horrible
need to maintain even Refl casts, because we might have `((a::kappa)
(b::Type))` where `kappa` is a unification variable that has already been
unified `kappa := Type -> Type`. This is only well-kinded if we can see
through that unification variable. So previously we used `mkNakedCastTy`
to add a stupid Refl cast. `((a::kappa) |> (Refl (Type->Type))
(b::Type)`. Not only is this unsavory, but it's also very fragile: many
functions (e.g. substitution) eliminate that Refl cast.
* `Note [The tcType invariant]` in `TcHsType`. This was closely related,
and was a delicate invariant about the result kind of `tc_hs_type`. It
forced a bunch of invariants on related functions.
The good news is that I was able to completely dispense with both
invariants.
I've introduced
* `Type.tcTypeKind :: TcType -> TcKind`. This is non-monadic, but
respects the distinction between `Type` and `Constraint`.
* `TcMType.tcTypeKindM :: TcType -> TcM TcKind`. This one is monadic, and
looks through unification variables.
You can call the former on any zonked `TcType`; but if the type may be
well-kinded only after zonking, you must use the latter.
It's always safe to use `tcTypeKindM`, but there are some times when it is
clearly safe to call `tcTypeKind`, and very convenient do to so without
resorting to the monad, such as in `TcErrors`. Sadly, it's not clear at
every call site which is the right one.
A number of other functions had to become monadic too
* `tcEqTypeM` (because it calls `tcTypeKindM`)
* `piResultTysM` (needed by `tcTypeKindM`)
* `splitPiTyInvisibleM`
* `invisibleTyBndrCountM`
* `tcTupKindSortM`
* `tcIsConstraintKindM`
* `isPredTyM`
All these functions appear together in `TcMType`.
All the mkNakedX functions go away, which is great.
This is all good, but I'm still unhappy.
* There are many calls to `isPredTy`, just to distinguish `->` from `=>`.
And we need `isPredTyM` now. I think we should just add an `ArgFlag` to
`FunTy`.
* These changes did not solve #15918 as we thought it would. The cause of
#15918 is that `mkCastTy` calls `isReflexiveCo`, which does not respect
the distinction between `Type` and `Constraint`. The reason `mkCastTy`
calls the blunderbuss `isReflexiveCo` is described in `Note [Respecting
definitional equality]` in `TyCoRep`.
So do we need a `mkTcCastTy`, wich ''does'' respect the
`Type`/`Constraint` distinction? And thence `mkTcAppTy` (since `mkAppTy`
calls `mkCastTy`), and `tcSubstTy` as well? This smells like bringing all
the `mkNakedX` functions back!
I rather wonder if, rather than having the complicated invariants
described in `Note [Respecting definitional equality]` we might instead
just make the `splitX` functions able to deal with casts?
Oddly, #15799 works in HEAD, and in this new branch; so the new stuff
can't claim to have fixed it.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/15952#comment:7>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list