BUG-TAG: Type inference for lambda parameters
The type checker incorrectly inferred `Any` for lambda parameters when a `Program` node was involved, preventing optimizations like constant folding. This was because the `check_params_tuple` function was resolving `TypeVar` to `StaticType::Any` instead of propagating the type variable. This commit addresses the issue by: - Explicitly wrapping the bound AST in a parameterless lambda within `compile_pipeline`. This ensures that the type checker always receives a `Lambda` node, even if the original input was a `Program` node. - Adding debug logging to the type checker to help diagnose similar issues in the future. Additionally, the commit fixes a bug where `parser.parse_program()` was used instead of `parser.parse_expression()`, which would consume the entire input and prevent checking for trailing expressions.
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
# Bug: Program-Node bricht Destructuring-Typinferenz
|
||||
|
||||
## Reproduktion
|
||||
|
||||
Ausgehend vom aktuellen Stand (Lambda-Wrapping in `compile_pipeline`, `parse_expression` in `compile`):
|
||||
|
||||
### Schritt 1: In `compile()` `parse_expression` durch `parse_program` ersetzen
|
||||
|
||||
In `src/ast/environment.rs`, Methode `compile()`:
|
||||
|
||||
```rust
|
||||
// VORHER (funktioniert):
|
||||
let syntax_ast = parser.parse_expression();
|
||||
|
||||
// NACHHER (Typinferenz bricht):
|
||||
let syntax_ast = parser.parse_program();
|
||||
```
|
||||
|
||||
Außerdem die `at_eof`-Prüfung entfernen (weil `parse_program` alles konsumiert).
|
||||
|
||||
### Schritt 2: Testen
|
||||
|
||||
```bash
|
||||
cargo run --release --bin ast -- -d -e "((fn [[x y]] (+ x y)) [10 20])"
|
||||
```
|
||||
|
||||
**Erwartet:** `Constant: 30` im Dump (Optimizer faltet den Ausdruck)
|
||||
|
||||
**Tatsächlich:** Kein Folding. Die Lambda-Parameter `x` und `y` haben Typ `Any` statt `Int`. HM step 10 (Unifikation) wird übersprungen weil `has_typevar_component` false ist.
|
||||
|
||||
### Schritt 3: Zusätzlich Lambda-Wrapping entfernen (verschärft das Problem)
|
||||
|
||||
In `compile_pipeline()` die Zeile `let wrapped = self.wrap_as_lambda(bound);` entfernen.
|
||||
|
||||
Dann bekommt `check_node_as_bound` einen `Program`-Node statt eines `Lambda`-Nodes. Ergebnis ist dasselbe: `Any`-Parameter, kein Folding.
|
||||
|
||||
## Ursache (unvollständig analysiert)
|
||||
|
||||
Der AST-Unterschied:
|
||||
|
||||
- **Funktioniert:** `Lambda(Call(Lambda([[x y]], body), [10 20]))` — kein Program-Node
|
||||
- **Bricht:** `Lambda(Program(Call(Lambda([[x y]], body), [10 20])))` — Program-Node dazwischen
|
||||
|
||||
Der TypeChecker erzeugt TypeVars (`?0`, `?1`) für die innere Lambda-Parameter. Aber in `check_params_tuple` (check.rs, Zeile ~241) wird `TypeVar` im Match auf `_ => StaticType::Any` aufgelöst statt propagiert. Dadurch enthält die Signatur `fn([[any any]]) -> int` statt `fn([[?0 ?1]]) -> int`, und HM step 10 überspringt die Unifikation.
|
||||
|
||||
Warum das nur mit Program-Node passiert und nicht ohne, ist unklar. Der `check_params_tuple`-Code hat sich nicht geändert.
|
||||
|
||||
## Betroffener Test
|
||||
|
||||
```
|
||||
tests/destructuring.rs::test_nested_destructuring_optimization
|
||||
```
|
||||
Reference in New Issue
Block a user