The fix correctly identifies that variables bound inside nominal patterns (like `s` in `Container.Box(s)`) are bound in the pattern scope and don't need to be captured. This results in cleaner canonical IR where functions that use nominal pattern matching are now represented as pure lambdas instead of closures with unnecessary captures. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
13 KiB
META
description=
type=file
SOURCE
Adv := [Val(U64, Str)].{
to_str : Adv -> Str
to_str = |Adv.Val(_, s)| s
to_u64 : Adv -> U64
to_u64 = |Adv.Val(u, _)| u
update_str : Adv, Str -> Adv
update_str = |Adv.Val(u64, _), next_str| Adv.Val(u64, next_str)
update_u64 : Adv, U64 -> Adv
update_u64 = |Adv.Val(_, str), next_u64| Adv.Val(next_u64, str)
}
mismatch = {
val = Adv.Val(10, "hello")
next_val = val.update_str(100)
next_val
}
mismatch2 = {
val = Adv.Val(10, "hello")
next_val = val.update_strr(100)
next_val
}
mismatch3 = {
next_val = "Hello".update(100)
next_val
}
main : (Str, U64)
main = {
val = Adv.Val(10, "hello")
next_val = val.update_str("world").update_u64(20)
(next_val.to_str(), next_val.to_u64())
}
EXPECTED
MISSING METHOD - Adv.md:17:28:17:31 MISSING METHOD - Adv.md:23:17:23:28 MISSING METHOD - Adv.md:28:21:28:27
PROBLEMS
MISSING METHOD This from_numeral method is being called on a value whose type doesn't have that method: Adv.md:17:28:17:31:
next_val = val.update_str(100)
^^^
The value's type, which does not have a method named from_numeral, is:
_Str_
Hint: For this to work, the type would need to have a method named from_numeral associated with it in the type's declaration.
MISSING METHOD This update_strr method is being called on a value whose type doesn't have that method: Adv.md:23:17:23:28:
next_val = val.update_strr(100)
^^^^^^^^^^^
The value's type, which does not have a method named update_strr, is:
_Adv_
Hint: For this to work, the type would need to have a method named update_strr associated with it in the type's declaration.
MISSING METHOD This update method is being called on a value whose type doesn't have that method: Adv.md:28:21:28:27:
next_val = "Hello".update(100)
^^^^^^
The value's type, which does not have a method named update, is:
_Str_
Hint: For this to work, the type would need to have a method named update associated with it in the type's declaration.
TOKENS
UpperIdent,OpColonEqual,OpenSquare,UpperIdent,NoSpaceOpenRound,UpperIdent,Comma,UpperIdent,CloseRound,CloseSquare,Dot,OpenCurly,
LowerIdent,OpColon,UpperIdent,OpArrow,UpperIdent,
LowerIdent,OpAssign,OpBar,UpperIdent,NoSpaceDotUpperIdent,NoSpaceOpenRound,Underscore,Comma,LowerIdent,CloseRound,OpBar,LowerIdent,
LowerIdent,OpColon,UpperIdent,OpArrow,UpperIdent,
LowerIdent,OpAssign,OpBar,UpperIdent,NoSpaceDotUpperIdent,NoSpaceOpenRound,LowerIdent,Comma,Underscore,CloseRound,OpBar,LowerIdent,
LowerIdent,OpColon,UpperIdent,Comma,UpperIdent,OpArrow,UpperIdent,
LowerIdent,OpAssign,OpBar,UpperIdent,NoSpaceDotUpperIdent,NoSpaceOpenRound,LowerIdent,Comma,Underscore,CloseRound,Comma,LowerIdent,OpBar,UpperIdent,NoSpaceDotUpperIdent,NoSpaceOpenRound,LowerIdent,Comma,LowerIdent,CloseRound,
LowerIdent,OpColon,UpperIdent,Comma,UpperIdent,OpArrow,UpperIdent,
LowerIdent,OpAssign,OpBar,UpperIdent,NoSpaceDotUpperIdent,NoSpaceOpenRound,Underscore,Comma,LowerIdent,CloseRound,Comma,LowerIdent,OpBar,UpperIdent,NoSpaceDotUpperIdent,NoSpaceOpenRound,LowerIdent,Comma,LowerIdent,CloseRound,
CloseCurly,
LowerIdent,OpAssign,OpenCurly,
LowerIdent,OpAssign,UpperIdent,NoSpaceDotUpperIdent,NoSpaceOpenRound,Int,Comma,StringStart,StringPart,StringEnd,CloseRound,
LowerIdent,OpAssign,LowerIdent,NoSpaceDotLowerIdent,NoSpaceOpenRound,Int,CloseRound,
LowerIdent,
CloseCurly,
LowerIdent,OpAssign,OpenCurly,
LowerIdent,OpAssign,UpperIdent,NoSpaceDotUpperIdent,NoSpaceOpenRound,Int,Comma,StringStart,StringPart,StringEnd,CloseRound,
LowerIdent,OpAssign,LowerIdent,NoSpaceDotLowerIdent,NoSpaceOpenRound,Int,CloseRound,
LowerIdent,
CloseCurly,
LowerIdent,OpAssign,OpenCurly,
LowerIdent,OpAssign,StringStart,StringPart,StringEnd,NoSpaceDotLowerIdent,NoSpaceOpenRound,Int,CloseRound,
LowerIdent,
CloseCurly,
LowerIdent,OpColon,OpenRound,UpperIdent,Comma,UpperIdent,CloseRound,
LowerIdent,OpAssign,OpenCurly,
LowerIdent,OpAssign,UpperIdent,NoSpaceDotUpperIdent,NoSpaceOpenRound,Int,Comma,StringStart,StringPart,StringEnd,CloseRound,
LowerIdent,OpAssign,LowerIdent,NoSpaceDotLowerIdent,NoSpaceOpenRound,StringStart,StringPart,StringEnd,CloseRound,NoSpaceDotLowerIdent,NoSpaceOpenRound,Int,CloseRound,
OpenRound,LowerIdent,NoSpaceDotLowerIdent,NoSpaceOpenRound,CloseRound,Comma,LowerIdent,NoSpaceDotLowerIdent,NoSpaceOpenRound,CloseRound,CloseRound,
CloseCurly,
EndOfFile,
PARSE
(file
(type-module)
(statements
(s-type-decl
(header (name "Adv")
(args))
(ty-tag-union
(tags
(ty-apply
(ty (name "Val"))
(ty (name "U64"))
(ty (name "Str")))))
(associated
(s-type-anno (name "to_str")
(ty-fn
(ty (name "Adv"))
(ty (name "Str"))))
(s-decl
(p-ident (raw "to_str"))
(e-lambda
(args
(p-tag (raw ".Val")
(p-underscore)
(p-ident (raw "s"))))
(e-ident (raw "s"))))
(s-type-anno (name "to_u64")
(ty-fn
(ty (name "Adv"))
(ty (name "U64"))))
(s-decl
(p-ident (raw "to_u64"))
(e-lambda
(args
(p-tag (raw ".Val")
(p-ident (raw "u"))
(p-underscore)))
(e-ident (raw "u"))))
(s-type-anno (name "update_str")
(ty-fn
(ty (name "Adv"))
(ty (name "Str"))
(ty (name "Adv"))))
(s-decl
(p-ident (raw "update_str"))
(e-lambda
(args
(p-tag (raw ".Val")
(p-ident (raw "u64"))
(p-underscore))
(p-ident (raw "next_str")))
(e-apply
(e-tag (raw "Adv.Val"))
(e-ident (raw "u64"))
(e-ident (raw "next_str")))))
(s-type-anno (name "update_u64")
(ty-fn
(ty (name "Adv"))
(ty (name "U64"))
(ty (name "Adv"))))
(s-decl
(p-ident (raw "update_u64"))
(e-lambda
(args
(p-tag (raw ".Val")
(p-underscore)
(p-ident (raw "str")))
(p-ident (raw "next_u64")))
(e-apply
(e-tag (raw "Adv.Val"))
(e-ident (raw "next_u64"))
(e-ident (raw "str")))))))
(s-decl
(p-ident (raw "mismatch"))
(e-block
(statements
(s-decl
(p-ident (raw "val"))
(e-apply
(e-tag (raw "Adv.Val"))
(e-int (raw "10"))
(e-string
(e-string-part (raw "hello")))))
(s-decl
(p-ident (raw "next_val"))
(e-field-access
(e-ident (raw "val"))
(e-apply
(e-ident (raw "update_str"))
(e-int (raw "100")))))
(e-ident (raw "next_val")))))
(s-decl
(p-ident (raw "mismatch2"))
(e-block
(statements
(s-decl
(p-ident (raw "val"))
(e-apply
(e-tag (raw "Adv.Val"))
(e-int (raw "10"))
(e-string
(e-string-part (raw "hello")))))
(s-decl
(p-ident (raw "next_val"))
(e-field-access
(e-ident (raw "val"))
(e-apply
(e-ident (raw "update_strr"))
(e-int (raw "100")))))
(e-ident (raw "next_val")))))
(s-decl
(p-ident (raw "mismatch3"))
(e-block
(statements
(s-decl
(p-ident (raw "next_val"))
(e-field-access
(e-string
(e-string-part (raw "Hello")))
(e-apply
(e-ident (raw "update"))
(e-int (raw "100")))))
(e-ident (raw "next_val")))))
(s-type-anno (name "main")
(ty-tuple
(ty (name "Str"))
(ty (name "U64"))))
(s-decl
(p-ident (raw "main"))
(e-block
(statements
(s-decl
(p-ident (raw "val"))
(e-apply
(e-tag (raw "Adv.Val"))
(e-int (raw "10"))
(e-string
(e-string-part (raw "hello")))))
(s-decl
(p-ident (raw "next_val"))
(e-field-access
(e-field-access
(e-ident (raw "val"))
(e-apply
(e-ident (raw "update_str"))
(e-string
(e-string-part (raw "world")))))
(e-apply
(e-ident (raw "update_u64"))
(e-int (raw "20")))))
(e-tuple
(e-field-access
(e-ident (raw "next_val"))
(e-apply
(e-ident (raw "to_str"))))
(e-field-access
(e-ident (raw "next_val"))
(e-apply
(e-ident (raw "to_u64"))))))))))
FORMATTED
Adv := [Val(U64, Str)].{
to_str : Adv -> Str
to_str = |Adv.Val(_, s)| s
to_u64 : Adv -> U64
to_u64 = |Adv.Val(u, _)| u
update_str : Adv, Str -> Adv
update_str = |Adv.Val(u64, _), next_str| Adv.Val(u64, next_str)
update_u64 : Adv, U64 -> Adv
update_u64 = |Adv.Val(_, str), next_u64| Adv.Val(next_u64, str)
}
mismatch = {
val = Adv.Val(10, "hello")
next_val = val.update_str(100)
next_val
}
mismatch2 = {
val = Adv.Val(10, "hello")
next_val = val.update_strr(100)
next_val
}
mismatch3 = {
next_val = "Hello".update(100)
next_val
}
main : (Str, U64)
main = {
val = Adv.Val(10, "hello")
next_val = val.update_str("world").update_u64(20)
(next_val.to_str(), next_val.to_u64())
}
CANONICALIZE
(can-ir
(d-let
(p-assign (ident "Adv.to_str"))
(e-lambda
(args
(p-nominal
(p-applied-tag)))
(e-lookup-local
(p-assign (ident "s"))))
(annotation
(ty-fn (effectful false)
(ty-lookup (name "Adv") (local))
(ty-lookup (name "Str") (builtin)))))
(d-let
(p-assign (ident "Adv.to_u64"))
(e-lambda
(args
(p-nominal
(p-applied-tag)))
(e-lookup-local
(p-assign (ident "u"))))
(annotation
(ty-fn (effectful false)
(ty-lookup (name "Adv") (local))
(ty-lookup (name "U64") (builtin)))))
(d-let
(p-assign (ident "Adv.update_str"))
(e-lambda
(args
(p-nominal
(p-applied-tag))
(p-assign (ident "next_str")))
(e-nominal (nominal "Adv")
(e-tag (name "Val")
(args
(e-lookup-local
(p-assign (ident "u64")))
(e-lookup-local
(p-assign (ident "next_str")))))))
(annotation
(ty-fn (effectful false)
(ty-lookup (name "Adv") (local))
(ty-lookup (name "Str") (builtin))
(ty-lookup (name "Adv") (local)))))
(d-let
(p-assign (ident "Adv.update_u64"))
(e-lambda
(args
(p-nominal
(p-applied-tag))
(p-assign (ident "next_u64")))
(e-nominal (nominal "Adv")
(e-tag (name "Val")
(args
(e-lookup-local
(p-assign (ident "next_u64")))
(e-lookup-local
(p-assign (ident "str")))))))
(annotation
(ty-fn (effectful false)
(ty-lookup (name "Adv") (local))
(ty-lookup (name "U64") (builtin))
(ty-lookup (name "Adv") (local)))))
(d-let
(p-assign (ident "mismatch"))
(e-block
(s-let
(p-assign (ident "val"))
(e-nominal (nominal "Adv")
(e-tag (name "Val")
(args
(e-num (value "10"))
(e-string
(e-literal (string "hello")))))))
(s-let
(p-assign (ident "next_val"))
(e-dot-access (field "update_str")
(receiver
(e-lookup-local
(p-assign (ident "val"))))
(args
(e-num (value "100")))))
(e-lookup-local
(p-assign (ident "next_val")))))
(d-let
(p-assign (ident "mismatch2"))
(e-block
(s-let
(p-assign (ident "val"))
(e-nominal (nominal "Adv")
(e-tag (name "Val")
(args
(e-num (value "10"))
(e-string
(e-literal (string "hello")))))))
(s-let
(p-assign (ident "next_val"))
(e-dot-access (field "update_strr")
(receiver
(e-lookup-local
(p-assign (ident "val"))))
(args
(e-num (value "100")))))
(e-lookup-local
(p-assign (ident "next_val")))))
(d-let
(p-assign (ident "mismatch3"))
(e-block
(s-let
(p-assign (ident "next_val"))
(e-dot-access (field "update")
(receiver
(e-string
(e-literal (string "Hello"))))
(args
(e-num (value "100")))))
(e-lookup-local
(p-assign (ident "next_val")))))
(d-let
(p-assign (ident "main"))
(e-block
(s-let
(p-assign (ident "val"))
(e-nominal (nominal "Adv")
(e-tag (name "Val")
(args
(e-num (value "10"))
(e-string
(e-literal (string "hello")))))))
(s-let
(p-assign (ident "next_val"))
(e-dot-access (field "update_u64")
(receiver
(e-dot-access (field "update_str")
(receiver
(e-lookup-local
(p-assign (ident "val"))))
(args
(e-string
(e-literal (string "world"))))))
(args
(e-num (value "20")))))
(e-tuple
(elems
(e-dot-access (field "to_str")
(receiver
(e-lookup-local
(p-assign (ident "next_val"))))
(args))
(e-dot-access (field "to_u64")
(receiver
(e-lookup-local
(p-assign (ident "next_val"))))
(args)))))
(annotation
(ty-tuple
(ty-lookup (name "Str") (builtin))
(ty-lookup (name "U64") (builtin)))))
(s-nominal-decl
(ty-header (name "Adv"))
(ty-tag-union
(ty-tag-name (name "Val")
(ty-lookup (name "U64") (builtin))
(ty-lookup (name "Str") (builtin))))))
TYPES
(inferred-types
(defs
(patt (type "Adv -> Str"))
(patt (type "Adv -> U64"))
(patt (type "Adv, Str -> Adv"))
(patt (type "Adv, U64 -> Adv"))
(patt (type "Adv"))
(patt (type "Error"))
(patt (type "Error"))
(patt (type "(Str, U64)")))
(type_decls
(nominal (type "Adv")
(ty-header (name "Adv"))))
(expressions
(expr (type "Adv -> Str"))
(expr (type "Adv -> U64"))
(expr (type "Adv, Str -> Adv"))
(expr (type "Adv, U64 -> Adv"))
(expr (type "Adv"))
(expr (type "Error"))
(expr (type "Error"))
(expr (type "(Str, U64)"))))