@@ -257,7 +257,10 @@ def mkNoConfusionCoreImp (indName : Name) : MetaM Unit := do
257257 (value := e)
258258 (hints := ReducibilityHints.abbrev)))
259259 setReducibleAttribute declName
260- modifyEnv fun env => markNoConfusion env declName
260+ let arity := info.numParams + 1 + 3 * (info.numIndices + 1 )
261+ let lhsPos := info.numParams + 1 + info.numIndices
262+ let rhsPos := info.numParams + 1 + info.numIndices + 1 + info.numIndices
263+ modifyEnv fun env => markNoConfusion env declName (.regular arity lhsPos rhsPos)
261264 modifyEnv fun env => addProtected env declName
262265
263266/--
@@ -295,48 +298,47 @@ def mkNoConfusionCtors (declName : Name) : MetaM Unit := do
295298 for ctor in indVal.ctors do
296299 let ctorInfo ← getConstInfoCtor ctor
297300 if ctorInfo.numFields > 0 then
298- let e ←
299- forallBoundedTelescope ctorInfo.type ctorInfo.numParams fun xs t => do
300- withLocalDeclD `P (.sort v) fun P =>
301- forallBoundedTelescope t ctorInfo.numFields fun fields1 _ => do
302- forallBoundedTelescope t ctorInfo.numFields fun fields2 _ => do
303- withPrimedNames fields2 do
304- withImplicitBinderInfos (xs ++ #[P] ++ fields1 ++ fields2) do
305- let ctor1 := mkAppN (mkConst ctor us) (xs ++ fields1)
306- let ctor2 := mkAppN (mkConst ctor us) (xs ++ fields2)
307- let is1 := (← whnf (← inferType ctor1)).getAppArgsN indVal.numIndices
308- let is2 := (← whnf (← inferType ctor2)).getAppArgsN indVal.numIndices
309- withNeededEqTelescope (is1.push ctor1) (is2.push ctor2) fun eqvs eqs => do
310- -- When the kernel checks this definition, it will perform the potentially expensive
311- -- computation that `noConfusionType h` is equal to `$kType → P`
312- let kType ← mkNoConfusionCtorArg ctor P
313- let kType := kType.beta (xs ++ fields1 ++ fields2)
314- withLocalDeclD `k kType fun k => do
315- let mut e := mkConst noConfusionName (v :: us)
316- e := mkAppN e (xs ++ #[P] ++ is1 ++ #[ctor1] ++ is2 ++ #[ctor2])
317- -- eqs may have more Eq rather than HEq than expected by `noConfusion`
318- for eq in eqs do
319- let needsHEq := (← whnfForall (← inferType e)).bindingDomain!.isHEq
320- if needsHEq && (← inferType eq).isEq then
321- e := mkApp e (← mkHEqOfEq eq)
322- else
323- e := mkApp e eq
324- e := mkApp e k
325- e ← mkExpectedTypeHint e P
326- mkLambdaFVars (xs ++ #[P] ++ fields1 ++ fields2 ++ eqvs ++ #[k]) e
327- let name := ctor.str "noConfusion"
328- addDecl (.defnDecl (← mkDefinitionValInferringUnsafe
329- (name := name)
330- (levelParams := recInfo.levelParams)
331- (type := (← inferType e))
332- (value := e)
333- (hints := ReducibilityHints.abbrev)
334- ))
335- setReducibleAttribute name
336- -- The compiler has special support for `noConfusion`. So lets mark this as
337- -- macroInline to not generate code for all these extra definitions, and instead
338- -- let the compiler unfold this to then put the custom code there
339- setInlineAttribute name (kind := .macroInline)
301+ forallBoundedTelescope ctorInfo.type ctorInfo.numParams fun xs t => do
302+ withLocalDeclD `P (.sort v) fun P =>
303+ forallBoundedTelescope t ctorInfo.numFields fun fields1 _ => do
304+ forallBoundedTelescope t ctorInfo.numFields fun fields2 _ => do
305+ withPrimedNames fields2 do
306+ withImplicitBinderInfos (xs ++ #[P] ++ fields1 ++ fields2) do
307+ let ctor1 := mkAppN (mkConst ctor us) (xs ++ fields1)
308+ let ctor2 := mkAppN (mkConst ctor us) (xs ++ fields2)
309+ let is1 := (← whnf (← inferType ctor1)).getAppArgsN indVal.numIndices
310+ let is2 := (← whnf (← inferType ctor2)).getAppArgsN indVal.numIndices
311+ withNeededEqTelescope (is1.push ctor1) (is2.push ctor2) fun eqvs eqs => do
312+ -- When the kernel checks this definition, it will perform the potentially expensive
313+ -- computation that `noConfusionType h` is equal to `$kType → P`
314+ let kType ← mkNoConfusionCtorArg ctor P
315+ let kType := kType.beta (xs ++ fields1 ++ fields2)
316+ withLocalDeclD `k kType fun k => do
317+ let mut e := mkConst noConfusionName (v :: us)
318+ e := mkAppN e (xs ++ #[P] ++ is1 ++ #[ctor1] ++ is2 ++ #[ctor2])
319+ -- eqs may have more Eq rather than HEq than expected by `noConfusion`
320+ for eq in eqs do
321+ let needsHEq := (← whnfForall (← inferType e)).bindingDomain!.isHEq
322+ if needsHEq && (← inferType eq).isEq then
323+ e := mkApp e (← mkHEqOfEq eq)
324+ else
325+ e := mkApp e eq
326+ e := mkApp e k
327+ e ← mkExpectedTypeHint e P
328+ e ← mkLambdaFVars (xs ++ #[P] ++ fields1 ++ fields2 ++ eqvs ++ #[k]) e
329+
330+ let name := ctor.str "noConfusion"
331+ addDecl (.defnDecl (← mkDefinitionValInferringUnsafe
332+ (name := name)
333+ (levelParams := recInfo.levelParams)
334+ (type := (← inferType e))
335+ (value := e)
336+ (hints := ReducibilityHints.abbrev)
337+ ))
338+ setReducibleAttribute name
339+ let arity := ctorInfo.numParams + 1 + 2 * ctorInfo.numFields + indVal.numIndices + 1
340+ let fields := kType.getNumHeadForalls
341+ modifyEnv fun env => markNoConfusion env name (.perCtor arity fields)
340342
341343
342344def mkNoConfusionCore (declName : Name) : MetaM Unit := do
@@ -375,7 +377,7 @@ where
375377 let ctorIdx := mkConst (mkCtorIdxName enumName) us
376378 mkLambdaFVars #[P, x, y] (← mkAppM ``noConfusionTypeEnum #[ctorIdx, P, x, y])
377379 let declName := Name.mkStr enumName "noConfusionType"
378- addAndCompile <| Declaration.defnDecl {
380+ addDecl <| Declaration.defnDecl {
379381 name := declName
380382 levelParams := v :: info.levelParams
381383 type := declType
@@ -404,7 +406,7 @@ where
404406 else
405407 mkAppOptM ``noConfusionEnum #[none, none, none, ctorIdx, P, x, y, h]
406408 let declName := Name.mkStr enumName "noConfusion"
407- addAndCompile <| Declaration.defnDecl {
409+ addDecl <| Declaration.defnDecl {
408410 name := declName
409411 levelParams := v :: info.levelParams
410412 type := declType
@@ -413,7 +415,7 @@ where
413415 hints := ReducibilityHints.abbrev
414416 }
415417 setReducibleAttribute declName
416- modifyEnv fun env => markNoConfusion env declName
418+ modifyEnv fun env => markNoConfusion env declName (.regular 4 1 2 )
417419
418420public def mkNoConfusion (declName : Name) : MetaM Unit := do
419421 withTraceNode `Meta.mkNoConfusion (fun _ => return m!"{declName}" ) do
0 commit comments