anistark / anistark/waspy

bug: a lambda parameter carries no type, so indexing or len() inside a lambda reads the wrong value

Đang mở
#115 0 bình luận 0 reaction 0 người được giao Xem trên GitHub
bug core-language priority-high
Ngôn ngữ chính
Rust
Star
22
Fork
6
Merge trung bình
1 ngày 3 giờ
Pull request đã merge (30 ngày)
6

Mô tả

## Description

A lambda's parameters carry no type, so any expression inside a lambda that needs its parameter's type reads the value as an untyped word. Indexing it, calling `len()` on it, or calling a method on it all produce a wrong answer, and compilation reports success.

This is a silent miscompile, which `plan/OVERVIEW.md`'s correctness rule treats as the highest-priority class: a compilation that reports success must give Python's answer or fail loudly.

## Steps to Reproduce

```python
def swap_first() -> int:
pair = (1, 5)
f = lambda kv: kv[1]
return f(pair)

def len_in_lambda() -> int:
g = lambda w: len(w)
return g("hello")
```

Compile with `just compile .py` (it succeeds) and run the exports:

| Function | waspy | CPython |
| --- | --- | --- |
| `swap_first()` | `0` | `5` |
| `len_in_lambda()` | `1819043176` | `5` |

`1819043176` is the first four bytes of `"hello"` read as an i32, which is what `len()` does when it treats a string offset as a collection pointer.

## Environment

- waspy 0.15.0, commit d7dcbc4
- Verified under both `wasmi` (the test harness) and Node 22

## Additional Context

A lambda parameter has no annotation, so `process_function_params` types it `Unknown`: https://github.com/anistark/waspy/blob/d7dcbc4/src/ir/converter.rs#L1056-L1059

The finalize pass lifts the lambda into a real module function and clones those params as they are, so the lifted function's parameter stays `Unknown`: https://github.com/anistark/waspy/blob/d7dcbc4/src/ir/finalize.rs#L163

`sorted()` refuses a key that reaches into its parameter rather than miscompiling it, which is the current mitigation and not a fix: https://github.com/anistark/waspy/blob/d7dcbc4/src/compiler/expression.rs#L2233

The fix is to type a lambda's parameters from its call sites, which is a typing pass of its own rather than a local change.

This is what stops `sorted(counts.items(), key=lambda kv: (-kv[1], kv[0]))` from being written the obvious way. `examples/text_report.py` sorts an explicit list of `(-count, word)` tuples instead, and says so in its docstring: https://github.com/anistark/waspy/blob/d7dcbc4/examples/text_report.py

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Hướng nghiên cứu

Start by compiling the two Python reproductions with `just compile` and compare the exported results with CPython. Read `src/ir/converter.rs` around `process_function_params`, `src/ir/finalize.rs` around lambda parameter lifting, and the mitigation in `src/compiler/expression.rs`; inspect `examples/text_report.py` for the affected sorting use case. Done means lambda expressions needing parameter types produce Python-compatible results or fail loudly.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
python, rust, wasm
Lĩnh vực
compilers
Loại issue
Lỗi
Độ khó
5/5
Thời gian dự kiến
Hơn một tuần
Mức độ hoạt động
Sôi nổi
Độ rõ ràng
Khá rõ ràng
Mức phù hợp với người mới
35/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.