Skip to content

GitLab

  • Menu
Projects Groups Snippets
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in / Register
  • GHC GHC
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 4,868
    • Issues 4,868
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
  • Merge requests 455
    • Merge requests 455
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
    • Test Cases
  • Deployments
    • Deployments
    • Releases
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Code review
    • Insights
    • Issue
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • Glasgow Haskell Compiler
  • GHCGHC
  • Issues
  • #14120
Closed
Open
Created Aug 15, 2017 by Ben Gamari@bgamari🐢Maintainer

Type comparison in stg-lint is hopelessly broken

Today I spent a fair amount of time looking at the STG linter, having encountered a number of times in the past six months where I needed to use it but noticed it was broken.

While I thought fixing it would just be a few small tweaks, it seems that with every issue I fix another bug rears its ugly head. So far I have encountered and fixed,

  • #14116 (closed)
  • #14117 (closed)
  • #14118 (closed)

The solutions to each of these has seemed rather obvious. However, now I seem to have run into a bit of a more fundamental issue:

Consider this excerpt extracted from Foreign.Storable,

{-# LANGUAGE BangPatterns #-}

module Hi where

import GHC.Word
import GHC.Ptr
import GHC.Base
import GHC.Num
import Data.Bits
import GHC.Fingerprint.Type

peekFingerprint :: Ptr Fingerprint -> IO Fingerprint
peekFingerprint p0 = do
      let peekW64 :: Ptr Word8 -> Int -> Word64 -> IO Word64
          peekW64 _  0  !i = return i
          peekW64 !p !n !i = peekW64 (p `plusPtr` 1) (n-1) (i `shiftL` 8)

      high <- peekW64 (castPtr p0) 8 0
      low  <- peekW64 (castPtr p0 `plusPtr` 8) 8 0
      return (Fingerprint high low)

In particular notice the castPtr application. This triggers the STG linter with,

ghc-stage1: panic! (the 'impossible' happened)
  (GHC version 8.3.20170815 for x86_64-unknown-linux):
	  *** Stg Lint ErrMsgs: in Stg2Stg ***
  <no location info>: warning:
       [in body of lambda with binders p0_s2zB :: Ptr Fingerprint,
                                       eta_s2zC :: State# RealWorld]
      In a function application, function type doesn't match arg types:
      Function type:
          Ptr Word8
          -> Int#
          -> Word#
          -> State# RealWorld
          -> (# State# RealWorld, Word64 #)
      Arg types:
          Ptr Fingerprint
          Int#
          Word#
          State# RealWorld
      Expression: $wpeekW64 p0_s2zB 8# 0## eta_s2zC

This is because by the time we are in Core Prep the castPtr is turned into a cast, which we discard in STG. Consequently, it seems that the comment attached to stgEqType,

stgEqType :: Type -> Type -> Bool
-- Compare types, but crudely because we have discarded
-- both casts and type applications, so types might look
-- different but be the same.  So reply "True" if in doubt.
-- "False" means that the types are definitely different.
--
-- Fundamentally this is a losing battle because of unsafeCoerce

is quite an understatement. Rather, there are exceedingly few cases where we can catch type errors in STG. I think the only case which we can reliably catch is that of two types with explicitly different primreps. It's not clear what we can/should do about this.

Edited Mar 10, 2019 by Ben Gamari
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking