You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit d389139
Browse filesBrowse the repository at this point in the historyBrowse files
Pass the origin of a synthesized match as an argument, not an attribute (#9128)
Why:
The type checker rewrites a `let` destructuring a GADT constructor, and
an optional parameter's default, into a match, and marked that match
with the string attributes `#let_gadt_pattern` and
`#optional_arg_default` so that it gets function-style diagnostics
rather than a switch's (#9126). Both are made and read inside typecore
and nothing after typing reads them. `type_expect` now takes
`?match_context` and `type_let` takes `?optional_default`; only
`let.unwrap`, which comes from the parsed `let?`, stays an attribute.
The GADT rewrite also required the binding to have no attributes, so a
doc comment or `@warning` in front of it was an error; its attributes
now go on the case pattern, and `@warning` on a pattern now covers that
pattern's unused variables.
Typedtree modified (let destructuring a GADT constructor):
Example:
type rec any = Any('a, 'a => string): any
let get = value => {
let Any(x, f) = value
f(x)
}
Before (typed):
expression
attribute "#let_gadt_pattern"
[]
Texp_match
expression
Texp_ident "value/1004"
[
<case>
pattern
Tpat_construct "Any"
…
After (typed):
expression
Texp_match
expression
Texp_ident "value/1004"
[
<case>
pattern
Tpat_construct "Any"
…
Diagnostic removed (attribute in front of a GADT let):
Example:
type rec any = Any('a, 'a => string): any
let get = value => {
/** Destructures the existential. */
let Any(x, f) = value
f(x)
}
Before (diagnostic):
This pattern introduces an existential type from a GADT constructor,
which is not allowed here. Match on it inside a switch instead.
After (diagnostic): compiles
Diagnostic removed (unused variable of a pattern with @warning):
Example:
let silenced = o =>
switch o {
| @warning("-27") Some(x) => 1
| None => 0
}
Before (diagnostic):
Warning number 27
unused variable x.
After (diagnostic): no warning
Review: Why not a typed origin field on `Texp_match`, as #9126 suggests? Nothing after typing reads the origin; the field would change the typed tree for no consumer.
Review: Does `@warning("-8")` on a GADT let cover a non-exhaustive pattern? No: the exhaustiveness check runs for the whole match, outside the case pattern's warning scope, as for a switch case.
Fixes: #9126
Claude-Session: https://claude.ai/code/session_01Kbf3gHnoR8Goys4AMxET4q
Signed-off-by: Christoph Knittel <ck@cca.io>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
- Accept an attribute or doc comment in front of a `let` that destructures a GADT constructor, and let `@warning` on a pattern cover that pattern's unused variables.
0 commit comments