fix: correctly compile irrelevant args to relevant ctor params (#9310)
This PR fixes IR constructor argument lowering to correctly handle an irrelevant argument being passed for a relevant parameter in all cases. This happened because constructor argument lowering (incompletely) reimplemented general LCNF-to-IR argument lowering, and the fix is to just adopt the generic helper functions. This is probably due to an incomplete refactoring when the new compiler was still on a branch.
This commit is contained in:
parent
5778a3c0f2
commit
837ea41ede
2 changed files with 53 additions and 23 deletions
|
|
@ -175,36 +175,27 @@ partial def lowerLet (decl : LCNF.LetDecl) (k : LCNF.Code) : M FnBody := do
|
|||
|
||||
assert! type == .object
|
||||
let ⟨ctorInfo, fields⟩ ← getCtorLayout name
|
||||
let args := args.extract (start := ctorVal.numParams)
|
||||
let irArgs := irArgs.extract (start := ctorVal.numParams)
|
||||
let objArgs : Array Arg ← do
|
||||
let mut result : Array Arg := #[]
|
||||
for i in *...fields.size do
|
||||
match args[i]! with
|
||||
| .fvar fvarId =>
|
||||
if let some (.var varId) := (← get).fvars[fvarId]? then
|
||||
if fields[i]! matches .object .. then
|
||||
result := result.push (.var varId)
|
||||
| .type _ | .erased =>
|
||||
if fields[i]! matches .object .. then
|
||||
result := result.push .irrelevant
|
||||
if fields[i]! matches .object .. then
|
||||
result := result.push irArgs[i]!
|
||||
pure result
|
||||
let objVar ← bindVar decl.fvarId
|
||||
let rec lowerNonObjectFields (_ : Unit) : M FnBody :=
|
||||
let rec loop (usizeCount : Nat) (i : Nat) : M FnBody := do
|
||||
match args[i]? with
|
||||
| some (.fvar fvarId) =>
|
||||
match (← get).fvars[fvarId]? with
|
||||
| some (.var varId) =>
|
||||
match fields[i]! with
|
||||
| .usize .. =>
|
||||
let k ← loop (usizeCount + 1) (i + 1)
|
||||
return .uset objVar (ctorInfo.size + usizeCount) varId k
|
||||
| .scalar _ offset argType =>
|
||||
let k ← loop usizeCount (i + 1)
|
||||
return .sset objVar (ctorInfo.size + ctorInfo.usize) offset varId argType k
|
||||
| .object .. | .irrelevant => loop usizeCount (i + 1)
|
||||
| _ => loop usizeCount (i + 1)
|
||||
| some (.type _) | some .erased => loop usizeCount (i + 1)
|
||||
match irArgs[i]? with
|
||||
| some (.var varId) =>
|
||||
match fields[i]! with
|
||||
| .usize .. =>
|
||||
let k ← loop (usizeCount + 1) (i + 1)
|
||||
return .uset objVar (ctorInfo.size + usizeCount) varId k
|
||||
| .scalar _ offset argType =>
|
||||
let k ← loop usizeCount (i + 1)
|
||||
return .sset objVar (ctorInfo.size + ctorInfo.usize) offset varId argType k
|
||||
| .object .. | .irrelevant => loop usizeCount (i + 1)
|
||||
| some .irrelevant => loop usizeCount (i + 1)
|
||||
| none => lowerCode k
|
||||
loop 0 0
|
||||
return .vdecl objVar type (.ctor ctorInfo objArgs) (← lowerNonObjectFields ())
|
||||
|
|
|
|||
39
tests/lean/run/ctorMixedRelevance.lean
Normal file
39
tests/lean/run/ctorMixedRelevance.lean
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
structure Value1 (α : Type) where
|
||||
fst : α
|
||||
|
||||
structure Value2 (α : Type) where
|
||||
snd : α
|
||||
|
||||
structure TwoThingies (α : Type) where
|
||||
value1 : Value1 α
|
||||
value2 : Value2 α
|
||||
|
||||
/--
|
||||
trace: [Compiler.IR] [result]
|
||||
def test1._closed_0 : obj :=
|
||||
let x_1 : obj := ctor_0[TwoThingies.mk] ◾ ◾;
|
||||
ret x_1
|
||||
def test1 : obj :=
|
||||
let x_1 : obj := test1._closed_0;
|
||||
ret x_1
|
||||
-/
|
||||
#guard_msgs in
|
||||
set_option trace.compiler.ir.result true in
|
||||
def test1 : TwoThingies Prop := { value1.fst := True, value2.snd := False }
|
||||
|
||||
/--
|
||||
trace: [Compiler.IR] [result]
|
||||
def test2._closed_0 : obj :=
|
||||
let x_1 : u8 := 0;
|
||||
let x_2 : u8 := 1;
|
||||
let x_3 : obj := box x_2;
|
||||
let x_4 : obj := box x_1;
|
||||
let x_5 : obj := ctor_0[TwoThingies.mk] x_3 x_4;
|
||||
ret x_5
|
||||
def test2 : obj :=
|
||||
let x_1 : obj := test2._closed_0;
|
||||
ret x_1
|
||||
-/
|
||||
#guard_msgs in
|
||||
set_option trace.compiler.ir.result true in
|
||||
def test2 : TwoThingies Bool := { value1.fst := true, value2.snd := false }
|
||||
Loading…
Add table
Reference in a new issue