Remove invalid unwrap annotation#138
Open
dillonkearns wants to merge 5 commits intomdgriffith:mainfrom
Open
Conversation
Elm.unwrapper generates a lambda that pattern matches on a
single-variant custom type:
\(Wrapper val) -> val
The previous annotation was `val -> unwrapped` — two generic type
variables. This annotation doesn't compile in Elm: the lambda body
extracts a concrete value (whatever `Wrapper` wraps), but the
annotation says ANY type, so Elm rejects it with a TYPE MISMATCH.
Any annotation we could generate would have the same problem,
because unwrapper doesn't know the inner type of the custom type
from just the name.
The fix is to omit the annotation entirely, letting Elm infer the
type from the custom type definition.
Before:
extract : val -> unwrapped
extract (Wrapper val) =
val
-- TYPE MISMATCH: `val` is `Int`, but the annotation says `unwrapped`
After:
extract (Wrapper val) =
val
-- Elm infers: extract : Wrapper -> Int
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a function's annotation is `Err []` (intentionally unknown, e.g. Elm.unwrapper's lambda), `applyType` now synthesizes a fresh generic return type instead of short-circuiting to `Err`. This restores inference in expressions like `1 + Elm.unwrap "Wrapper" wrapped`, which previously lost their signature when the unwrap bug was fixed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Became dead when unwrapper's annotation switched to `Err []`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
# Conflicts: # tests/TypeChecking.elm
`apply fn []` with an unknown fn type should still be unknown (the result is the fn itself, whose type we still don't know), rather than gaining a synthesized return type out of thin air. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
49028d3 to
7af311a
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Say we are writing codegen for a type like:
Elm.unwrapandElm.unwrappergenerate a lambda that pattern matches on a single-variant custom type:The argument pattern matches on
Wrapper, so the argument type should be theWrappervariant's type, not a generic type variable (Elm gives an error if you use a generic type variable):Before:
Since we don't know the type name (
MyTypein the example I gave above) we can't infer it so we short-circuit the type annotation by returningErr [].After:
If you know the types, pipe through
Elm.withTypeto attach them:Returning
Err []fromunwrapperwould have lost inference for outer expressions too, sinceapplyTypeused to short-circuit on anyErr. For example,Elm.Op.plus (Elm.int 1) (Elm.unwrap [] "Wrapper" wrapped)would produce no signature at all. SoapplyTypenow distinguishesErr [](intentionally unknown) fromErr [errors](an actual inference failure). When the function annotation isErr [], it synthesizes a fresh generic return type so downstream inference still flows, and the outer declaration still getsfoo : Int.If you would prefer to do a bigger refactor to have a custom type to represent an unknown inference value instead of having special meaning for
Err [], we could totally do that too, just let me know!