The Inst.shortCutIntLit mechanism in the type checker was missing cases
where a floating-point literal was given without an explicit decimal point.
As a result, programs with lots of floating-point literals (without decimals)
ended up with massive Static Reference Tables. This is not cool. See
comments with Trac #783 for details.
\begin{code}
shortCutIntLit :: Integer -> TcType -> Maybe (HsExpr TcId)
shortCutIntLit i ty
\begin{code}
shortCutIntLit :: Integer -> TcType -> Maybe (HsExpr TcId)
shortCutIntLit i ty
- | isIntTy ty && inIntRange i -- Short cut for Int
- = Just (HsLit (HsInt i))
- | isIntegerTy ty -- Short cut for Integer
- = Just (HsLit (HsInteger i ty))
- | otherwise = Nothing
+ | isIntTy ty && inIntRange i = Just (HsLit (HsInt i))
+ | isIntegerTy ty = Just (HsLit (HsInteger i ty))
+ | otherwise = shortCutFracLit (fromInteger i) ty
+ -- The 'otherwise' case is important
+ -- Consider (3 :: Float). Syntactically it looks like an IntLit,
+ -- so we'll call shortCutIntLit, but of course it's a float
+ -- This can make a big difference for programs with a lot of
+ -- literals, compiled without -O
shortCutFracLit :: Rational -> TcType -> Maybe (HsExpr TcId)
shortCutFracLit f ty
shortCutFracLit :: Rational -> TcType -> Maybe (HsExpr TcId)
shortCutFracLit f ty
- | isFloatTy ty
- = Just (mk_lit floatDataCon (HsFloatPrim f))
- | isDoubleTy ty
- = Just (mk_lit doubleDataCon (HsDoublePrim f))
- | otherwise = Nothing
+ | isFloatTy ty = Just (mk_lit floatDataCon (HsFloatPrim f))
+ | isDoubleTy ty = Just (mk_lit doubleDataCon (HsDoublePrim f))
+ | otherwise = Nothing
where
mk_lit con lit = HsApp (nlHsVar (dataConWrapId con)) (nlHsLit lit)
where
mk_lit con lit = HsApp (nlHsVar (dataConWrapId con)) (nlHsLit lit)