Now that golden tests were merged in, I moved back to the original issue but I have a couple of questions regarding the hints that are generated in case of a TypesDoNotUnify
error.
Using this code a = [{ a: 1, b: 2 }, { a: 1 }]
, these are the hints before stripRedundantHints
is called:
[ ErrorUnifyingTypes
(RCons
( SourceSpan
{ spanName = ""
, spanStart = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
, spanEnd = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
}
, []
)
Label { runLabel = "a" }
(TypeConstructor
( SourceSpan
{ spanName = ""
, spanStart = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
, spanEnd = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
}
, []
)
(Qualified
(Just (ModuleName [ ProperName { runProperName = "Prim" } ]))
ProperName { runProperName = "Int" }))
(RCons
( SourceSpan
{ spanName = ""
, spanStart = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
, spanEnd = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
}
, []
)
Label { runLabel = "b" }
(TypeConstructor
( SourceSpan
{ spanName = ""
, spanStart = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
, spanEnd = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
}
, []
)
(Qualified
(Just (ModuleName [ ProperName { runProperName = "Prim" } ]))
ProperName { runProperName = "Int" }))
(REmpty
( SourceSpan
{ spanName = ""
, spanStart = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
, spanEnd = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
}
, []
))))
(RCons
( SourceSpan
{ spanName = ""
, spanStart = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
, spanEnd = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
}
, []
)
Label { runLabel = "a" }
(TypeConstructor
( SourceSpan
{ spanName = ""
, spanStart = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
, spanEnd = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
}
, []
)
(Qualified
(Just (ModuleName [ ProperName { runProperName = "Prim" } ]))
ProperName { runProperName = "Int" }))
(REmpty
( SourceSpan
{ spanName = ""
, spanStart = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
, spanEnd = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
}
, []
)))
, ErrorUnifyingTypes
(RCons
( SourceSpan
{ spanName = ""
, spanStart = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
, spanEnd = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
}
, []
)
Label { runLabel = "a" }
(TypeConstructor
( SourceSpan
{ spanName = ""
, spanStart = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
, spanEnd = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
}
, []
)
(Qualified
(Just (ModuleName [ ProperName { runProperName = "Prim" } ]))
ProperName { runProperName = "Int" }))
(RCons
( SourceSpan
{ spanName = ""
, spanStart = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
, spanEnd = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
}
, []
)
Label { runLabel = "b" }
(TypeConstructor
( SourceSpan
{ spanName = ""
, spanStart = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
, spanEnd = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
}
, []
)
(Qualified
(Just (ModuleName [ ProperName { runProperName = "Prim" } ]))
ProperName { runProperName = "Int" }))
(REmpty
( SourceSpan
{ spanName = ""
, spanStart = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
, spanEnd = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
}
, []
))))
(RCons
( SourceSpan
{ spanName = ""
, spanStart = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
, spanEnd = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
}
, []
)
Label { runLabel = "a" }
(TypeConstructor
( SourceSpan
{ spanName = ""
, spanStart = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
, spanEnd = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
}
, []
)
(Qualified
(Just (ModuleName [ ProperName { runProperName = "Prim" } ]))
ProperName { runProperName = "Int" }))
(REmpty
( SourceSpan
{ spanName = ""
, spanStart = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
, spanEnd = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
}
, []
)))
, ErrorUnifyingTypes
(TUnknown
( SourceSpan
{ spanName = ""
, spanStart = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
, spanEnd = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
}
, []
)
2)
(TypeApp
( SourceSpan
{ spanName = ""
, spanStart = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
, spanEnd = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
}
, []
)
(TypeConstructor
( SourceSpan
{ spanName = ""
, spanStart = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
, spanEnd = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
}
, []
)
(Qualified
(Just (ModuleName [ ProperName { runProperName = "Prim" } ]))
ProperName { runProperName = "Record" }))
(RCons
( SourceSpan
{ spanName = ""
, spanStart = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
, spanEnd = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
}
, []
)
Label { runLabel = "a" }
(TypeConstructor
( SourceSpan
{ spanName = ""
, spanStart = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
, spanEnd = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
}
, []
)
(Qualified
(Just (ModuleName [ ProperName { runProperName = "Prim" } ]))
ProperName { runProperName = "Int" }))
(REmpty
( SourceSpan
{ spanName = ""
, spanStart = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
, spanEnd = SourcePos { sourcePosLine = 0 , sourcePosColumn = 0 }
}
, []
))))
, PositionedError
(SourceSpan
{ spanName = "tests/purs/passing/2138.purs"
, spanStart = SourcePos { sourcePosLine = 7 , sourcePosColumn = 5 }
, spanEnd = SourcePos { sourcePosLine = 7 , sourcePosColumn = 31 }
} :|
[])
, ErrorInferringType
(PositionedValue
SourceSpan
{ spanName = "tests/purs/passing/2138.purs"
, spanStart = SourcePos { sourcePosLine = 7 , sourcePosColumn = 5 }
, spanEnd = SourcePos { sourcePosLine = 7 , sourcePosColumn = 31 }
}
[]
(Literal
SourceSpan
{ spanName = "tests/purs/passing/2138.purs"
, spanStart = SourcePos { sourcePosLine = 7 , sourcePosColumn = 5 }
, spanEnd = SourcePos { sourcePosLine = 7 , sourcePosColumn = 31 }
}
(ArrayLiteral
[ PositionedValue
SourceSpan
{ spanName = "tests/purs/passing/2138.purs"
, spanStart = SourcePos { sourcePosLine = 7 , sourcePosColumn = 6 }
, spanEnd = SourcePos { sourcePosLine = 7 , sourcePosColumn = 20 }
}
[]
(Literal
SourceSpan
{ spanName = "tests/purs/passing/2138.purs"
, spanStart = SourcePos { sourcePosLine = 7 , sourcePosColumn = 6 }
, spanEnd = SourcePos { sourcePosLine = 7 , sourcePosColumn = 20 }
}
(ObjectLiteral
[ ( "a"
, PositionedValue
SourceSpan
{ spanName = "tests/purs/passing/2138.purs"
, spanStart =
SourcePos { sourcePosLine = 7 , sourcePosColumn = 11 }
, spanEnd = SourcePos { sourcePosLine = 7 , sourcePosColumn = 12 }
}
[]
(Literal
SourceSpan
{ spanName = "tests/purs/passing/2138.purs"
, spanStart =
SourcePos { sourcePosLine = 7 , sourcePosColumn = 11 }
, spanEnd = SourcePos { sourcePosLine = 7 , sourcePosColumn = 12 }
}
(NumericLiteral (Left 1)))
)
, ( "b"
, PositionedValue
SourceSpan
{ spanName = "tests/purs/passing/2138.purs"
, spanStart =
SourcePos { sourcePosLine = 7 , sourcePosColumn = 17 }
, spanEnd = SourcePos { sourcePosLine = 7 , sourcePosColumn = 18 }
}
[]
(Literal
SourceSpan
{ spanName = "tests/purs/passing/2138.purs"
, spanStart =
SourcePos { sourcePosLine = 7 , sourcePosColumn = 17 }
, spanEnd = SourcePos { sourcePosLine = 7 , sourcePosColumn = 18 }
}
(NumericLiteral (Left 2)))
)
]))
, PositionedValue
SourceSpan
{ spanName = "tests/purs/passing/2138.purs"
, spanStart =
SourcePos { sourcePosLine = 7 , sourcePosColumn = 22 }
, spanEnd = SourcePos { sourcePosLine = 7 , sourcePosColumn = 30 }
}
[]
(Literal
SourceSpan
{ spanName = "tests/purs/passing/2138.purs"
, spanStart =
SourcePos { sourcePosLine = 7 , sourcePosColumn = 22 }
, spanEnd = SourcePos { sourcePosLine = 7 , sourcePosColumn = 30 }
}
(ObjectLiteral
[ ( "a"
, PositionedValue
SourceSpan
{ spanName = "tests/purs/passing/2138.purs"
, spanStart =
SourcePos { sourcePosLine = 7 , sourcePosColumn = 27 }
, spanEnd = SourcePos { sourcePosLine = 7 , sourcePosColumn = 28 }
}
[]
(Literal
SourceSpan
{ spanName = "tests/purs/passing/2138.purs"
, spanStart =
SourcePos { sourcePosLine = 7 , sourcePosColumn = 27 }
, spanEnd = SourcePos { sourcePosLine = 7 , sourcePosColumn = 28 }
}
(NumericLiteral (Left 1)))
)
]))
])))
, PositionedError
(SourceSpan
{ spanName = "tests/purs/passing/2138.purs"
, spanStart = SourcePos { sourcePosLine = 7 , sourcePosColumn = 1 }
, spanEnd = SourcePos { sourcePosLine = 7 , sourcePosColumn = 31 }
} :|
[])
, ErrorInValueDeclaration (Ident "a")
, ErrorInModule
(ModuleName [ ProperName { runProperName = "Main" } ])
]
Which, if I’m not wrong, simplifies to (using some pseudo-code):
[ ErrorUnifyingTypes ( a :: Int, b :: Int ) ( a :: Int )
, ErrorUnifyingTypes ( a :: Int, b :: Int ) ( a :: Int )
, ErrorUnifyingTypes TUnknown (a :: Int)
, PositionedError ...
, ErrorInferringType ...
, PositionedError ...
, ErrorInValueDeclaration ...
, ErrorInModule
]
The first two hints are apparently always repeated, and that’s why they’re passed through stripRedundantHints
.
What I’m doing now is removing the other ErrorUnifyingTypes
hint when it matches the TypesDoNotUnify
error.
The first problem is that I’m left with that TUnknown
hint. I can arbitrarly remove it, and it works fine in this situation, but I’m moderately sure that it would mess up cases where the type is actually uknown.
The second problem is that with nested records the “list of hints” goes something like this:
[(b :: Int) (c :: Int), { b :: Int } { c :: Int }, { a :: { b :: Int } } { a :: { c :: Int } }]
.
I can remove the the first hint by matching types, and the second one by extracting the row from the record, but then it gets trickier (and worse in case of deeper nestings, I guess).
I guess an hackish solution could be removing all the ErrorUnifyingTypes
hints in case the first one matches the error, but I have no idea whether this is going to mess other things up (and I don’t know whether there are enough golden tests to cover this).
The other solution would be fixing the produced hints, but before going down that path I’d rather have some opinions on this first!
p.s. to debug this I’ve temporarily added pretty-show
as a dependency, it made my life 100x easier