Summary
store <var> as <call> emits an ERROR-level Could not infer type for variable '<var>' whenever the called action's return type is statically Unknown — which is the normal case for any action that returns an expression built from its (untyped) parameters. The program runs correctly and exits 0; only the static diagnostic is wrong, and it is very noisy.
This is the same gradual-typing philosophy as #567 (an Unknown value means "statically unknown", not "known incompatible"), but on the VariableDeclaration inference path, which #587 did not touch. It is not limited to list indexing — #567's inventory attributes the Could not infer type cascade to "indexing an untyped parameter", but the reproduction below has no lists or indexing at all.
Environment
Minimal reproduction
define action called add_one with parameters n:
return n plus 1
end action
define action called use_it:
store x as add_one of 3
return x
end action
display use_it
Output (the program runs and prints 4):
Type checking warnings:
error[ERROR]: Could not infer type for variable 'x'
┌─ repro.wfl:6:5
│
6 │ store x as add_one of 3
│ ^ Type error occurred here
4
Exit code: 0 (non-fatal).
Note the severity/header inconsistency too: the block is titled Type checking warnings: but the item is labelled error[ERROR].
Scoping the trigger
| Case |
RHS |
Result |
store x as add_one of 3 where add_one returns n plus 1 (untyped param → Unknown return) |
Unknown |
❌ Could not infer type for variable 'x' |
store x as gives_text where gives_text returns "hello" (concrete return type) |
Text |
✅ no diagnostic |
display add_one of 3 — the same call used directly, no store |
— |
✅ no diagnostic |
So the trigger is specifically binding an Unknown-typed call result to a variable with store. Callee-before-caller vs. callee-after-caller makes no difference (both fire).
Root cause
Statement::VariableDeclaration in src/typechecker/mod.rs treats an inferred Type::Unknown as an error:
// src/typechecker/mod.rs (~line 638)
if inferred_type == Type::Unknown && !is_container_property_assignment {
self.type_error(
format!("Could not infer type for variable '{name}'"),
None, None, *_line, *_column,
);
}
Under gradual typing, Unknown here means "statically unknown", which should bind x as Unknown silently — mirroring #587's own change for #567 ("Referencing a binding with no recorded type now yields Unknown silently instead of raising Cannot determine type of variable"). The VariableDeclaration arm just needs the same treatment: when inferred_type == Type::Unknown, record the variable as Unknown and do not raise a type_error.
Impact
Any action that returns an expression involving its parameters has an Unknown return type, so any caller that does store result as helper of ... gets flagged. In a real program built entirely from small mutually-recursive helpers, this dominates the output: the Scribe templating engine emits 104 of these notes on a fully-correct run (out of 106 total diagnostics), which drowns out anything real. Repro:
define action called wrap with parameters s:
return "[" with s with "]"
end action
define action called go:
store a as wrap of "x" // Unknown return -> flagged
store b as wrap of a // flagged
return b
end action
display go // prints [[x]], exit 0
Related
Suggested fix / test
In the VariableDeclaration arm, drop the type_error when inferred_type == Type::Unknown (bind the symbol as Unknown and continue). A regression test: the minimal repro above should type-check clean and run, printing 4 with no error[ERROR] on stderr.
Summary
store <var> as <call>emits an ERROR-levelCould not infer type for variable '<var>'whenever the called action's return type is staticallyUnknown— which is the normal case for any action that returns an expression built from its (untyped) parameters. The program runs correctly and exits 0; only the static diagnostic is wrong, and it is very noisy.This is the same gradual-typing philosophy as #567 (an
Unknownvalue means "statically unknown", not "known incompatible"), but on theVariableDeclarationinference path, which #587 did not touch. It is not limited to list indexing — #567's inventory attributes theCould not infer typecascade to "indexing an untyped parameter", but the reproduction below has no lists or indexing at all.Environment
main@2c52826(i.e. after Fix five GitHub issues: string coercion, parameter shadowing, operators, scope, typing #587 / Typechecker: Any/Unknown values from list indexing and untyped parameters rejected by strict ERROR rules (false positives) #567's partial fix), Linux, release buildMinimal reproduction
Output (the program runs and prints
4):Exit code: 0 (non-fatal).
Note the severity/header inconsistency too: the block is titled
Type checking warnings:but the item is labellederror[ERROR].Scoping the trigger
store x as add_one of 3whereadd_onereturnsn plus 1(untyped param →Unknownreturn)UnknownCould not infer type for variable 'x'store x as gives_textwheregives_textreturns"hello"(concrete return type)Textdisplay add_one of 3— the same call used directly, nostoreSo the trigger is specifically binding an
Unknown-typed call result to a variable withstore. Callee-before-caller vs. callee-after-caller makes no difference (both fire).Root cause
Statement::VariableDeclarationinsrc/typechecker/mod.rstreats an inferredType::Unknownas an error:Under gradual typing,
Unknownhere means "statically unknown", which should bindxasUnknownsilently — mirroring #587's own change for #567 ("Referencing a binding with no recorded type now yieldsUnknownsilently instead of raisingCannot determine type of variable"). TheVariableDeclarationarm just needs the same treatment: wheninferred_type == Type::Unknown, record the variable asUnknownand do not raise atype_error.Impact
Any action that returns an expression involving its parameters has an
Unknownreturn type, so any caller that doesstore result as helper of ...gets flagged. In a real program built entirely from small mutually-recursive helpers, this dominates the output: the Scribe templating engine emits 104 of these notes on a fully-correct run (out of 106 total diagnostics), which drowns out anything real. Repro:Related
11x Could not infer type for variable '...'but attributes it to indexing. Fix five GitHub issues: string coercion, parameter shadowing, operators, scope, typing #587 addressed several of Typechecker: Any/Unknown values from list indexing and untyped parameters rejected by strict ERROR rules (false positives) #567's items and theCannot determine type of variablemessage, but thisVariableDeclaration-pathCould not infer typediagnostic still fires (verified on2c52826), and it reproduces with no indexing at all.Suggested fix / test
In the
VariableDeclarationarm, drop thetype_errorwheninferred_type == Type::Unknown(bind the symbol asUnknownand continue). A regression test: the minimal repro above should type-check clean and run, printing4with noerror[ERROR]on stderr.