Skip to content

Unexpected behavior with INLINE pragma

I have not been able to create a small isolated test case that illustrates the problem because there are too many dependencies on other code, but I will upload a small tarball that illustrates the problem.

I have the following code:

{-# INLINE triple #-}
triple :: Subject -> Predicate -> Object -> Triple
triple subj pred obj
  | isLNode subj     =  error $ "subject must be UNode or BNode: " ++ show subj
  | isBNode pred     =  error $ "predicate must be UNode, not BNode: " ++ show pred ++ debug pred -- 1
  | isLNode pred     =  error $ "predicate must be UNode, not LNode: " ++ show pred    -- 2
  | otherwise        =  Triple subj pred obj
  where debug (UNode _)    = " [UNode]"
        debug (BNode _)    = " [BNode]"
        debug (BNodeGen _) = " [BNodeGen]"
        debug (LNode _)    = " [LNode]"

{-# INLINE isBNode #-}
isBNode :: Node -> Bool
isBNode (BNode _)    = True
isBNode (BNodeGen _) = True
isBNode _            = False

{-# INLINE isLNode #-}
isLNode :: Node -> Bool
isLNode (LNode _) = True
isLNode _         = False

data Node =  
  UNode {-# UNPACK #-} !FastString
  | BNode {-# UNPACK #-} !FastString
  | BNodeGen  {-# UNPACK #-} !Int
  | LNode {-# UNPACK #-} !LValue

When this along with all the other supporting code is compiled with -O2, then on a particular test file, the error branch labeled 1 in the triple function above is entered, even though the guard test should have evaluated to false. The error message calls the debug function which shows that the type of node was a UNode, but as you can see, isBNode should always evaluate to false unless the node is a BNode or BNodeGen.

The exact error message is:

ttlparse: predicate must be UNode, not BNode: <(0, http://www.w3.org/2001/sw/DataAccess/df1/tests/test-00.ttl#x)> [UNode]

If I change the INLINE pragma to NOINLINE, the problem disappears, and the code takes the otherwise branch as it is supposed to.

Now the really bizarre behavior: if I switch the two guard lines 1 and 2 in the above code, then it runs fine with no error, even with the INLINE pragma.

The data is the same in both cases, and the triple function is the same apart from the order of the second guard and the third guard.

As I stated, using NOINLINE, it doesn't matter which of the guards labeled 1 and 2 is first, but with the INLINE pragma, there is an error if the order is 1 2 but no error if the order is 2 1.

To see the problem, save the tarball and do the following:

tar xzf rdf4h.tar.gz
chmod u+x debug.sh
./debug.sh

The debug.sh script builds the project and runs the test, which will error out with the message I included above.

If you then edit RDF.hs and switch lines 138 and 139 (labeled as 1 and 2 in the code above), you should then see a different message that is the result of successfully parsing the file.

Please let me know if you have any questions or I can help in any way.

Trac metadata
Trac field Value
Version 6.8.1
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information