Skip to content

Commit d762884

Browse files
fix(typecheck): lenient deref so *ref-mode-param type-checks (#128) (#190)
Params declared with a ref/mut mode (e.g. `ref self`, `ref other: Int`) are lowered to their bare value type — the borrow checker tracks the actual borrow, not the type. But OpDeref required the operand to unify with `TRef tv`, so stdlib code reading ref params via `*self`/`*other` (traits.affine Eq/Ord/Hash/Display impls for Int/Bool) failed with `Unify (ref tv, Int)`. Make `*e` peel one borrow layer when e is TRef/TMut/TOwn and act as the identity on a value type. Real reference types still deref to inner; value types unchanged -> no regression. stdlib 16->17/19; 233/233 dune test, zero regression. Refs #128 Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 367197d commit d762884

1 file changed

Lines changed: 12 additions & 0 deletions

File tree

lib/typecheck.ml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,18 @@ let rec synth (ctx : context) (expr : expr) : ty result =
940940
| _ ->
941941
let* () = unify_or_err operand_ty ty_int in
942942
Ok ty_int)
943+
| OpDeref ->
944+
(* Lenient deref: `*e` peels one borrow layer when `e` is a
945+
reference type, but is the identity on a value type. Params
946+
declared with a `ref`/`mut` mode are lowered to their bare
947+
value type (the borrow checker tracks the actual borrow), so
948+
stdlib code that reads them via `*self` / `*other` must still
949+
type-check. Real `TRef`/`TMut`/`TOwn` still peel to the inner
950+
type. *)
951+
let* operand_ty = synth ctx operand in
952+
(match repr operand_ty with
953+
| TRef t | TMut t | TOwn t -> Ok t
954+
| t -> Ok t)
943955
| _ ->
944956
let (operand_ty, result_ty) = type_of_unop op in
945957
let* () = check ctx operand operand_ty in

0 commit comments

Comments
 (0)