Note [Why does Case have a 'Type' field?]
The obvious alternative is
exprType (Case scrut bndr alts)
| (_,_,rhs1):_ <- alts
= exprType rhs1
But caching the type in the Case constructor
exprType (Case scrut bndr ty alts) = ty
is better for at least three reasons:
* It works when there are no alternatives (see case invariant 1 above)
* It might be faster in deeply-nested situations.
* It might not be quite the same as (exprType rhs) for one
of the RHSs in alts. Consider a phantom type synonym
type S a = Int
and we want to form the case expression
case x of { K (a::*) -> (e :: S a) }
Then exprType of the RHS is (S a), but we cannot make that be
the 'ty' in the Case constructor because 'a' is simply not in
scope there. Instead we must expand the synonym to Int before
putting it in the Case constructor. See GHC.Core.Utils.mkSingleAltCase.
So we'd have to do synonym expansion in exprType which would
be inefficient.
* The type stored in the case is checked with lintInTy. This checks
(among other things) that it does not mention any variables that are
not in scope. If we did not have the type there, it would be a bit
harder for Core Lint to reject case blah of Ex x -> x where
data Ex = forall a. Ex a. References 0
This Note does not link to any other.
Referenced by 2
- GHC.Core call site
- Case expression invariants GHC.Core