Type error existence assertions idea

I’m working on a library that exports functions with very complicated typeclass instances. One of the reasons they’re complicated is to rule out invalid inputs to certain functions (which have the aforementioned constraints in their type signature). For testing purposes, I’d like to be able to assert that function f fails to typecheck when supplied with a specific input, say, x. The only way to do this currently is to plug the value into f and get a type error. But of course I can’t make this quasi-“assertion” in my actual tests, since then I can’t run my test suite (because it’s now plagued by a type error).

I was wondering what some of you might think about adding a new keyword that effectively just checks for the existence of type errors. Something like:

assertShouldNotTypeCheck f x

which doesn’t compile to anything, and raises a compiler error iff f x isn’t a type error. Then my tests can include this new kind of assertion (even though they’re doing nothing at runtime). What do you all think?

(I made another language feature suggestion 9 days ago - if I’m making too many of these, or should be placing them elsewhere, sincere apologies!)

1 Like

As far as I know, the PureScript compiler doesn’t understand the difference between a compile-time error in your code and one in your test-suit.

If you look at the PureScript Book (PureScript by Example), you’ll note that they have you comment/uncomment test cases as you can not run/check earlier tests if later tests don’t compile.

That being said, you can use Bash and check if the compiler’s output is what you expect. That might be a way to automate tests that you expect the compiler fail on. Not sure what the shortcomings of such an approach are other than how slow it will be to compile for each test.

The compiler already has some level of support for this, it’s just used internally for the compilers development:


failingTests :: SpecWith SupportModules
failingTests = do
  failingTestCases <- runIO $ getTestFiles "failing"

  describe "Failing examples" $ do
    forM_ failingTestCases $ \testPurs -> do
      let mainPath = getTestMain testPurs
      it ("'" <> takeFileName mainPath <> "' should fail to compile") $ \support -> do
        expectedFailures <- getShouldFailWith mainPath
        assertDoesNotCompile support testPurs expectedFailures

I’m not sure if it’s worth exposing this functionality, as it’d be fairly easy to recreate outside of the compiler

1 Like