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 |