Skip to content

Commit 310abce

Browse files
authored
fix: boxing may have to correct let binder types (#11426)
This PR closes #11356.
1 parent 2da5b52 commit 310abce

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

src/Lean/Compiler/IR/Boxing.lean

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,8 +267,29 @@ def visitVDeclExpr (x : VarId) (ty : IRType) (e : Expr) (b : FnBody) : M FnBody
267267
| _ =>
268268
return .vdecl x ty e b
269269

270+
/--
271+
Up to this point the type system of IR is quite loose so we can for example encounter situations
272+
such as
273+
```
274+
let y : obj := f x
275+
```
276+
where `f : obj -> uint8`. It is the job of the boxing pass to enforce a stricter obj/scalar
277+
separation and as such it needs to correct situations like this.
278+
-/
279+
def tryCorrectVDeclType (ty : IRType) (e : Expr) : M IRType :=
280+
match e with
281+
| .fap f _ => do
282+
let decl ← getDecl f
283+
return decl.resultType
284+
| .pap .. => return .object
285+
| .uproj .. => return .usize
286+
| .ctor .. | .reuse .. | .ap .. | .lit .. | .sproj .. | .proj .. | .reset .. =>
287+
return ty
288+
| .unbox .. | .box .. | .isShared .. => unreachable!
289+
270290
partial def visitFnBody : FnBody → M FnBody
271291
| .vdecl x t v b => do
292+
let t ← tryCorrectVDeclType t v
272293
let b ← withVDecl x t v (visitFnBody b)
273294
visitVDeclExpr x t v b
274295
| .jdecl j xs v b => do

tests/lean/run/boxing_bug.lean

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
def myCast : NatCast UInt8 where
2+
natCast := UInt8.ofNat
3+
4+
class Semiring (α : Type u) where
5+
[nsmul : SMul Nat α]
6+
7+
/--
8+
trace: [Compiler.IR] [result]
9+
def instSemiringUInt8._lam_0 (x_1 : @& tobj) (x_2 : u8) : u8 :=
10+
let x_3 : u8 := UInt8.ofNat x_1;
11+
let x_4 : u8 := UInt8.mul x_3 x_2;
12+
ret x_4
13+
def instSemiringUInt8 : obj :=
14+
let x_1 : obj := pap instSemiringUInt8._lam_0._boxed;
15+
ret x_1
16+
def instSemiringUInt8._lam_0._boxed (x_1 : tobj) (x_2 : tagged) : tagged :=
17+
let x_3 : u8 := unbox x_2;
18+
let x_4 : u8 := instSemiringUInt8._lam_0 x_1 x_3;
19+
dec x_1;
20+
let x_5 : tagged := box x_4;
21+
ret x_5
22+
-/
23+
#guard_msgs in
24+
set_option trace.compiler.ir.result true in
25+
attribute [local instance] myCast UInt8.intCast in
26+
instance : Semiring UInt8 where
27+
nsmul := ⟨(· * ·)⟩
28+

0 commit comments

Comments
 (0)