Repository navigation
fix(hy-check): reject non-lowered O8 map-slot borrows in var, assign, and struct-lit positions (HYB-E3104) - #1424
Conversation
… and struct-lit positions (HYB-E3104) Fixes limitlessprojects#1423
22332ec to
721093b
Compare
|
Verified and subsumed by #1441, which we just landed on main (merge onto post-#1432 tip, battery 1775/0 · corpus tripwire clear · differential FULL 40+86) — credit-closing rather than landing both. Your five scenarios, probed against the landed tree:
Both PRs restrict loan marking/gating to the positions hy-emit actually lowers (define/let without type ascription, all-ident assign targets). #1441 carries the same gates plus the call-argument position coverage (52-line test file, merged verbatim), so nothing from your diff is missing. One implementation note: your struct-field early-continue keyed on Credit: you and @Dimank92 (#1441) independently spotted the same non-lowered-position gap. The landed fix keeps your five repro shapes pinned green. |
Fixes #1423
Problem
On
main(7d63d5f),Checker::check_stmt_addr_of_loan_projectionsandChecker::walk_addr_of_loan_projectionsincompiler/crates/hy-check/src/addr_loan.rsexempt&m[k](allow_slot_loan_root = true) in four positions wherehy-emit(compiler/crates/hy-emit/src/stmt.rs) never lowers&m[k]as an O8 map-slot loan:vardeclarations (LocalKind::Var,var p = &m["a"]/var p *acct = &m["a"]):emit_local_in_seq(stmt.rs:295-323,371-386) only lowersLocalKind::Define | LocalKind::Letbindings withl.ty.is_none()andl.names.len() == l.values.len(), returning early forLocalKind::Var.ptrs[0] = &m["a"],*pp = &m["a"]):emit_assign_in_seq(stmt.rs:1207-1213) only lowersAssignOp::Assignstatements whentargets.len() == values.len()and every target isPlaceKind::Ident(_).q, arr[0] = &m["a"], 1): becausetargets.iter().all(|t| matches!(&t.kind, PlaceKind::Ident(_)))is false when any parallel target is an index or field place,hy-emitemits&m["a"]verbatim even for the identifier targetq.Expr::StructLitfields on structs not rejected by A6 (struct box { p any }; b := box{p: &m["a"]}):walk_addr_of_loan_projections(addr_loan.rs:390) unconditionally skippedself.map_slot_borrow_span(st, &f.value).is_some()assuming A6 (HYB-E3103) had already fired on the struct declaration, which does not happen forany-typed or generic type-parameter fields (andcontinue;also skipped recursing into nested operands underStmt::ReturnandExpr::StructLit).All four shapes pass
hyb checkwith0 diagnostics(Verdict::Accept) and failhyb build(go build:invalid operation: cannot take address of m["a"]), violatingGUARANTEES.mdRow 13 (accepted-implies-buildable) andT24(HYB-E3104).Fix
In
compiler/crates/hy-check/src/addr_loan.rs:allow_rootinStmt::Local(l)(check_stmt_addr_of_loan_projections) andmark_slot_loans_localtoLocalKind::Define | LocalKind::Letwithl.ty.is_none() && l.names.len() == l.values.len()(preservingLocalKind::ConstforHYB-E6003).allow_rootinStmt::Assign(check_stmt_addr_of_loan_projections) andmark_slot_loans_assignto*op == AssignOp::Assign && targets.len() == values.len() && targets.iter().all(|t| matches!(&t.kind, PlaceKind::Ident(_))), while exempting directPlaceKind::Fieldroot borrows that are already owned byA6(HYB-E3103).Expr::StructLit, only exempt a root&m[k]field value whenHYB-E3103has already been recorded, and recurse throughwalk_addr_of_loan_projections(..., allow_root)in bothStmt::ReturnandExpr::StructLitso nested loan projections are still checked.Verification
compiler/crates/hy-check/tests/non_lowered_slot_loan_positions.rscoveringvar p = &m["a"],var p *acct = &m["a"],ptrs[0] = &m["a"],q, arr[0] = &m["a"], 1,box{p: &m["a"]}, and positive controls (q := &m["a"],q = &m["a"], and A6b.p = &m["a"]).cargo test --manifest-path compiler/Cargo.toml --workspace --quietpython3 tools/check_corpus_census.pypython3 tools/check_conflict_markers.pypython3 tools/check_test_registration.pypython3 tools/corpus_harness.py --bin target/debug/hybpython3 tools/managed_gate.py target/debug/hyb gates/managed-baseline.json tests/checker-corpus/02-shared-map-managed.hy tests/checker-corpus/18-pool-shared-struct-managed.hypython3 tools/differential_loop.py --bin target/debug/hyb