Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
c71982f
Report arity mismatch for type aliases instead of silently returning …
MikaelMayer May 29, 2026
9c8aace
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer May 29, 2026
907a4ad
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer May 29, 2026
d4812e6
ci: retry after transient cache miss in downstream jobs
MikaelMayer May 29, 2026
21a3f50
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer May 29, 2026
60e8e1c
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer May 29, 2026
f4830da
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer May 29, 2026
5fb6607
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer Jun 1, 2026
6a95cfe
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer Jun 1, 2026
c2a17c7
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer Jun 1, 2026
5f805a4
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer Jun 1, 2026
a60bc8b
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer Jun 1, 2026
ad55381
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer Jun 1, 2026
33bd612
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer Jun 2, 2026
2373662
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer Jun 3, 2026
c6b02d0
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer Jun 3, 2026
6a5eb8f
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer Jun 4, 2026
b09accb
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer Jun 4, 2026
119dc19
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer Jun 5, 2026
bc38f45
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer Jun 5, 2026
ae84d01
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer Jun 5, 2026
c94a1ce
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer Jun 5, 2026
9a5a730
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer Jun 6, 2026
2e7263c
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer Jun 8, 2026
ed4b23f
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer Jun 8, 2026
cbf3abd
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer Jun 8, 2026
c6e1c78
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer Jun 9, 2026
14845a9
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer Jun 10, 2026
f03a165
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer Jun 10, 2026
89892e0
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer Jun 11, 2026
7173272
ci: delete stale cache before saving to prevent downstream cache misses
MikaelMayer Jun 11, 2026
170315b
ci: save lake cache even when a prior step fails
MikaelMayer Jun 11, 2026
eaa2c93
ci: revert cache delete step that caused downstream cache miss
MikaelMayer Jun 11, 2026
e11e769
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer Jun 11, 2026
4639671
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer Jun 11, 2026
bde83c1
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer Jun 11, 2026
738b50f
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer Jun 11, 2026
c1ef8f6
Merge remote-tracking branch 'origin/main2' into issue-1239-lambda-ty…
MikaelMayer Jun 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ jobs:
lake-package-directory: StrataCLI
use-github-cache: false
- name: Save lake cache
if: '!cancelled()'
uses: ./.github/actions/save-lake-cache
with:
path: |
Expand Down
36 changes: 29 additions & 7 deletions Strata/DL/Lambda/LExprTypeEnv.lean
Original file line number Diff line number Diff line change
Expand Up @@ -886,6 +886,18 @@ theorem LTy_subst_instantiate {IDMeta : Type} [ToFormat IDMeta]
instance : Inhabited (Option LMonoTy × TEnv IDMeta) where
default := (none, TEnv.default)

/-- Check whether `name` matches an alias but with the wrong number of type
arguments. Returns an error on arity mismatch, or `.ok ()` otherwise. -/
def LMonoTy.checkAliasArity (name : String) (args : LMonoTys)
(aliases : List TypeAlias) : Except Format Unit :=
match aliases.find? (fun a => a.name == name) with
| none => .ok ()
| some alias =>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖🔍 Nit: find? returns the first alias matching by name. If the alias list ever contains multiple entries with the same name but different arities (e.g., overloaded aliases), the error message will report the arity of whichever appears first, which may not be the one the user intended. Consider whether the error message should list all registered arities for that name (e.g., "expected 1 or 3 type argument(s)").

Context

This is a minor edge case — if aliases are unique by name (which seems likely given the AliasesWF invariant), this is a non-issue. But if overloading by arity is ever supported, this would produce a confusing message.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Good observation. As you noted, aliases are unique by name in the current system — TContext.AliasesWF ensures per-alias well-formedness, and the alias registration path does not allow duplicate names. The tconsAlias function already matches by name+arity, so checkAliasArity is only reached when no exact match exists. If overloading by arity is ever supported, we would need to revisit this, but for now the single-arity message is correct.

if alias.typeArgs.length == args.length then .ok ()
else .error f!"Arity mismatch for type alias '{name}': \
expected {alias.typeArgs.length} type argument(s), \
got {args.length}"

/--
Return the instantiated definition of `.tcons name args` if it is a registered
type alias.
Expand All @@ -900,7 +912,10 @@ def LMonoTy.tconsAlias [ToFormat IDMeta] (name : String) (args : LMonoTys)
let matchingAlias := Env.context.aliases.find?
(fun a => a.name == name && a.typeArgs.length == args.length)
match matchingAlias with
| none => return (inputMty, Env)
| none =>
-- Check for arity mismatch: name matches but arity doesn't.
LMonoTy.checkAliasArity name args Env.context.aliases
return (inputMty, Env)
| some alias =>
-- Create instantiation pair: [alias pattern, alias definition].
-- The alias pattern and definition share the same type variables here.
Expand Down Expand Up @@ -949,7 +964,9 @@ check whether the de-aliased types are registered/known.
def LMonoTy.aliasDef? [ToFormat IDMeta] (mty : LMonoTy) (Env : TEnv IDMeta)
: Except Format (LMonoTy × TEnv IDMeta) := do
match mty with
| .tcons name args => return (LMonoTy.tconsAliasSimple name args Env.context.aliases, Env)
| .tcons name args =>
LMonoTy.checkAliasArity name args Env.context.aliases
return (LMonoTy.tconsAliasSimple name args Env.context.aliases, Env)
| .bitvec _ | .ftvar _ => return (mty, Env)

mutual
Expand Down Expand Up @@ -1670,8 +1687,11 @@ theorem tconsAlias_tyGen_mono
-- Case split on whether a matching alias is found
split at h
case h_1 =>
-- No matching alias: Env' = Env
simp [Pure.pure, Except.pure] at h; obtain ⟨_, h2⟩ := h; subst h2; omega
-- No matching alias: split on checkAliasArity
simp only [Bind.bind, Except.bind] at h
split at h
· simp at h
· simp [Pure.pure, Except.pure] at h; obtain ⟨_, h2⟩ := h; subst h2; omega
case h_2 alias_val =>
-- Matching alias found: calls instantiateEnv then unify + updateSubst
split at h
Expand All @@ -1690,10 +1710,12 @@ theorem aliasDef_tyGen_mono
(mty' : LMonoTy) (Env' : TEnv T.IDMeta)
(h : LMonoTy.aliasDef? mty Env = .ok (mty', Env')) :
Env'.genEnv.genState.tyGen ≥ Env.genEnv.genState.tyGen := by
simp only [LMonoTy.aliasDef?] at h
simp only [LMonoTy.aliasDef?, Bind.bind, Except.bind] at h
split at h
· -- tconsAliasSimple doesn't change Env
simp [Pure.pure, Except.pure] at h; obtain ⟨_, h2⟩ := h; subst h2; omega
· -- .tcons case: split on checkAliasArity
split at h
· simp at h
· simp [Pure.pure, Except.pure] at h; obtain ⟨_, h2⟩ := h; subst h2; omega
· simp [Pure.pure, Except.pure] at h; obtain ⟨_, h2⟩ := h; subst h2; omega
· simp [Pure.pure, Except.pure] at h; obtain ⟨_, h2⟩ := h; subst h2; omega

Expand Down
7 changes: 5 additions & 2 deletions Strata/DL/Lambda/LExprTypeSpec.lean
Original file line number Diff line number Diff line change
Expand Up @@ -4602,8 +4602,11 @@ theorem tconsAlias_eq_simple
match ma with
| none =>
unfold LMonoTy.tconsAlias at h_tcons; rw [h_find] at h_tcons
simp at h_tcons
obtain ⟨h1, h2⟩ := h_tcons; rw [← h1, ← h2]
simp only [Bind.bind, Except.bind] at h_tcons
split at h_tcons
· contradiction
· simp at h_tcons
obtain ⟨h1, h2⟩ := h_tcons; rw [← h1, ← h2]
| some alias =>
have h_alias_wf := h_aliases_wf alias (List.mem_of_find?_eq_some h_find)
have h_pred := List.find?_some h_find
Expand Down
13 changes: 12 additions & 1 deletion StrataTest/DL/Lambda/LExprTypeEnvTests.lean
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ Subst:
type := mty[bool]}]} )
return format ans

/-- info: ok: myInt -/
/-- info: error: Arity mismatch for type alias 'myInt': expected 1 type argument(s), got 0 -/
#guard_msgs in
#eval do let (ans, _) ← LMonoTy.aliasDef? mty[myInt]
( (@TEnv.default String).updateContext
Expand Down Expand Up @@ -121,6 +121,17 @@ Subst:
type := mty[bool]}]} )
return (format ans)

-- Test: arity mismatch produces a clear error (issue #1239)
/-- info: error: Arity mismatch for type alias 'MyAlias': expected 1 type argument(s), got 2 -/
#guard_msgs in
#eval do let (ans, _) ← LMonoTy.aliasDef? mty[MyAlias int bool]
( (@TEnv.default String).updateContext
{ aliases := [{
typeArgs := ["a"],
name := "MyAlias",
type := mty[Wrapped %a]}] })
return format ans

/-- info: false -/
#guard_msgs in
#eval isInstanceOfKnownType mty[myTy (myTy)]
Expand Down
Loading