roc icon indicating copy to clipboard operation
roc copied to clipboard

Adding invalid implementation for a function creates error messages in other parts of the code

Open jwoudenberg opened this issue 1 year ago • 7 comments

I've been running into a weird error while implementing a decoder. Below is the code simplified as far as I can while still triggering the error:

interface Foo
    exposes [validFn]
    imports []

invalidFn : {} -> *
# invalidFn = \_ -> validFn {} (\_ -> Foo)

validFn : a, (a -> [Foo]) -> a
validFn = \s, toMaybe ->
    h : a -> a
    h = \x ->
        when toMaybe x is
            Foo -> invalidFn {}

    h s

This compilers. Now uncomment the invalidFn line, and you get the following errors:

>   roc test Foo.roc

── TYPE MISMATCH in package/Rocon.roc ──────────────────────────────────────────

This expression is used in an unexpected way:

6│  invalidFn = \_ -> validFn {} (\_ -> Foo)
                      ^^^^^^^^^^^^^^^^^^^^^^

This validFn call produces:

    {}

But you are trying to use it as:

    *

Tip: The type annotation uses the type variable * to say that this
definition can produce any type of value. But in the body I see that
it will only produce a record value of a single specific type. Maybe
change the type annotation to be more specific? Maybe change the code
to be more general?


── TYPE MISMATCH in package/Rocon.roc ──────────────────────────────────────────

This 1st argument to toMaybe has an unexpected type:

12│          when toMaybe x is
                          ^

This x value is a:

    a

But toMaybe needs its 1st argument to be:

    a

────────────────────────────────────────────────────────────────────────────────

2 errors and 0 warnings found in 28 ms

That first error is helpful, but the second one I don't think is:

  • The error message is saying Roc is expecting an a and getting an a, so what's the problem?
  • It's weird that adding an implementation for one function creates a compiler error in an entirely different function.
  • In my original case I got 34 extra errors in various seemingly unrelated parts of the code instead of just the one here, and those 34 burried the useful error 😅.

jwoudenberg avatar Mar 16 '24 16:03 jwoudenberg

Thanks for this minimal reproduction @jwoudenberg! This is an interesting one :)

The error message is saying Roc is expecting an a and getting an a, so what's the problem?

The a is scoped to one definition, not to the entire function or file, so those are not inherently the same a. That being said, I don't know why that mismatch occurs :smile: I'll open a new issue for that.

It's weird that adding an implementation for one function creates a compiler error in an entirely different function.

Note that you did not just add an implementation here. The type does not match the implementation, so I can see how this changes things when the compiler tries to make the implementation work.

In my original case I got 34 extra errors in various seemingly unrelated parts of the code instead of just the one here, and those 34 burried the useful error

I also think these were caused by the compiler trying to make the implementation work with a different type then before.

Anton-4 avatar Mar 18 '24 16:03 Anton-4

Can we close this in favor of #6595 @jwoudenberg?

Anton-4 avatar Mar 18 '24 17:03 Anton-4

Sure, thank you!

jwoudenberg avatar Mar 18 '24 20:03 jwoudenberg

Hey @Anton-4 , quick follow up question to your comments:

Note that you did not just add an implementation here. The type does not match the implementation, so I can see how this changes things when the compiler tries to make the implementation work.

I also think these were caused by the compiler trying to make the implementation work with a different type then before.

Do you mean to say that the compiler will infer the correct type for invalidFn which is different from the one I specified, and that inferred type then causes a type-error in validFn?

jwoudenberg avatar Mar 18 '24 20:03 jwoudenberg

Do you mean to say that the compiler will infer the correct type for invalidFn which is different from the one I specified, and that inferred type then causes a type-error in validFn?

I believe that is the case, I'd have to do some investigating to confirm that.

Anton-4 avatar Mar 19 '24 09:03 Anton-4

If I try with this simple code sample:

interface Foo
    exposes [foo]
    imports []

foo : U8 -> U8
foo = \_ -> {}

bar : U8
bar = foo 4

Then I just get a compile error for foo. The compiler doesn't give an additional compiler error in bar, which uses foo correctly according to its type signature, but not according to its implementation.

This behavior is matches my expectations too. I often add type signatures to contain type errors in a bit of code, making sure that if I make an error in one place it doesn't result in a type error in a completely different bit of code. That does appear to be happening here.

Going to reopen in that light, but please let me know if you disagree!

jwoudenberg avatar Mar 19 '24 12:03 jwoudenberg

Interesting! Yeah, this warrants further investigation.

Anton-4 avatar Mar 19 '24 12:03 Anton-4