Have typechecking produce HsType Typechecked instead of Type
Right now, there is an unfortunate lack of parallelism between expressions and types. When an expression is typechecked, it is transformed from
HsExpr Name to
HsExpr TcId. When a type is typechecked, it is transformed from
HsType Name to
This arrangement has served us well enough for some time, but it has several drawbacks:
- Validity checking is really meant to be done over user-written syntax. This bit when implementing #11715, when validity checking couldn't tell the difference between
Int => Int(bad) and
Int -> Int(good). There may be other opportunities for simplification by having the user-written syntax available.
- The situation above extends to type-level declarations. That is, an
HsDecl Namefor a datatype goes straight to a
TyCon, instead of to a typechecked form of source. This is problematic because it means that all of typechecking must happen twice. The first is to figure out the kind of the
TyCon(the is the
kcpass); the actual result is discarded. Then, typechecking is repeated with the known
TyConkind; this pass should always succeed and is more like desugaring than typechecking. But all the constraint generation and solving happens again.
- This second pass uses knot-tied
TyCons, leading to
Note [Type-checking inside the knot]in !TsHsType.
If we have a form of types in
HsSyn that occurs after typechecking, we can fix the above problems, leading both to a runtime improvement (no double-checking type declarations) and code simplification (no more typechecking in the knot).
This is a significant refactor, and it should proceed in at least two stages: one for just plain types, and one for type declarations.
Note that we can't produce
HsType TcTyVar, because
HsType Name sometimes become
TyCons and sometimes become
TcTyVars. We really need
HsType (TyCon + TcTyVar) or some such. But perhaps it would be better to wait until after refactoring with respect to the Trees That Grow paper.