fix: accidental ownership with specialization

This commit is contained in:
Sebastian Ullrich 2024-05-24 18:20:31 +02:00
parent 745d77b068
commit d85d3d5f3a
5 changed files with 57 additions and 15 deletions

View file

@ -24,12 +24,12 @@ abbrev Index := Nat
/-- Variable identifier -/
structure VarId where
idx : Index
deriving Inhabited
deriving Inhabited, Repr
/-- Join point identifier -/
structure JoinPointId where
idx : Index
deriving Inhabited
deriving Inhabited, Repr
abbrev Index.lt (a b : Index) : Bool := a < b
@ -83,7 +83,7 @@ inductive IRType where
| irrelevant | object | tobject
| struct (leanTypeName : Option Name) (types : Array IRType) : IRType
| union (leanTypeName : Name) (types : Array IRType) : IRType
deriving Inhabited
deriving Inhabited, Repr
namespace IRType
@ -236,7 +236,7 @@ structure Param where
x : VarId
borrow : Bool
ty : IRType
deriving Inhabited
deriving Inhabited, Repr
@[export lean_ir_mk_param]
def mkParam (x : VarId) (borrow : Bool) (ty : IRType) : Param := ⟨x, borrow, ty⟩

View file

@ -258,7 +258,8 @@ def preserveTailCall (x : VarId) (v : Expr) (b : FnBody) : M Unit := do
let ctx ← read
match v, b with
| (Expr.fap g ys), (FnBody.ret (Arg.var z)) =>
if ctx.decls.any (·.name == g) && x == z then
-- NOTE: we currently support TCO for self-calls only
if ctx.currFn == g && x == z then
let ps ← getParamInfo (ParamMap.Key.decl g)
ownParamsUsingArgs ys ps
| _, _ => pure ()

25
tests/lean/4240.lean Normal file
View file

@ -0,0 +1,25 @@
/-! Check for bug accidentally marking `m` as owned. -/
class MyClass (α : Type u) where
instance : MyClass Nat where
inductive MyOption (α : Type u) where
| none
| some (key : α)
namespace MyOption
def isSomeWithInstance [MyClass α] : MyOption α → Bool
| none => false
| some _ => true
def isSome : MyOption α → Bool
| none => false
| some _ => true
end MyOption
set_option trace.compiler.ir.result true in
def isSomeWithInstanceNat (m : { m : Array (MyOption Nat) // 0 < m.size }) : Bool :=
(m.1.uget 0 m.2).isSomeWithInstance

View file

@ -0,0 +1,26 @@
[result]
def MyOption.isSomeWithInstance._at.isSomeWithInstanceNat._spec_1 (x_1 : @& obj) : u8 :=
case x_1 : obj of
MyOption.none →
let x_2 : u8 := 0;
ret x_2
MyOption.some →
let x_3 : u8 := 1;
ret x_3
def isSomeWithInstanceNat (x_1 : @& obj) : u8 :=
let x_2 : usize := 0;
let x_3 : obj := Array.uget ◾ x_1 x_2 ◾;
let x_4 : u8 := MyOption.isSomeWithInstance._at.isSomeWithInstanceNat._spec_1 x_3;
dec x_3;
ret x_4
def MyOption.isSomeWithInstance._at.isSomeWithInstanceNat._spec_1._boxed (x_1 : obj) : obj :=
let x_2 : u8 := MyOption.isSomeWithInstance._at.isSomeWithInstanceNat._spec_1 x_1;
dec x_1;
let x_3 : obj := box x_2;
ret x_3
def isSomeWithInstanceNat._boxed (x_1 : obj) : obj :=
let x_2 : u8 := isSomeWithInstanceNat x_1;
dec x_1;
let x_3 : obj := box x_2;
ret x_3

View file

@ -1,10 +0,0 @@
set_option trace.compiler.ir.result true
-- should be tail calls
mutual
partial def even (a : Nat) : Nat := if a == 0 then 1 else odd (a - 1)
partial def odd (a : Nat) : Nat := if a == 0 then 0 else even (a - 1)
end