@@ -80,6 +80,16 @@ def ProjReductionKind.toUInt64 : ProjReductionKind → UInt64
8080 | .yesWithDelta => 2
8181 | .yesWithDeltaI => 3
8282
83+ structure CanUnfoldPredicateConfig where
84+ toBool : Bool
85+ deriving Inhabited, Repr
86+
87+ @ [inline, expose, match_pattern]
88+ def CanUnfoldPredicateConfig.default : CanUnfoldPredicateConfig := ⟨false ⟩
89+
90+ @ [inline, expose, match_pattern]
91+ def CanUnfoldPredicateConfig.atMatcher : CanUnfoldPredicateConfig := ⟨true ⟩
92+
8393/--
8494Configuration flags for the `MetaM` monad.
8595Many of them are used to control the `isDefEq` function that checks whether two terms are definitionally equal or not.
@@ -194,6 +204,11 @@ structure Config where
194204 When `zeta := true`, then `zetaHave := false` disables zeta reduction of `have` expressions.
195205 -/
196206 zetaHave : Bool := true
207+ /--
208+ A predicate to control whether a constant can be unfolded or not at `whnf`.
209+ Ignored if `Context.customCanUnfoldPredicate?` is set.
210+ -/
211+ canUnfoldPredicateConfig : CanUnfoldPredicateConfig := .default
197212 deriving Inhabited, Repr
198213
199214/-- Convert `isDefEq` and `WHNF` relevant parts into a key for caching results -/
@@ -216,7 +231,8 @@ private def Config.toKey (c : Config) : UInt64 :=
216231 (c.etaStruct.toUInt64 <<< 17 ) |||
217232 (c.proj.toUInt64 <<< 19 ) |||
218233 (c.zetaHave.toUInt64 <<< 21 ) |||
219- (c.zetaUnused.toUInt64 <<< 22 )
234+ (c.zetaUnused.toUInt64 <<< 22 ) |||
235+ (c.canUnfoldPredicateConfig.toBool.toUInt64 <<< 23 )
220236
221237/-- Configuration with key produced by `Config.toKey`. -/
222238structure ConfigWithKey where
@@ -230,6 +246,16 @@ instance : Inhabited ConfigWithKey where -- #9463
230246def Config.toConfigWithKey (c : Config) : ConfigWithKey :=
231247 { config := c }
232248
249+ def ConfigWithKey.withCanUnfoldAtMatcherPred (c : ConfigWithKey) : ConfigWithKey :=
250+ { config := { c.config with canUnfoldPredicateConfig := .atMatcher },
251+ key :=
252+ have : CanUnfoldPredicateConfig.atMatcher.toBool = true := rfl
253+ c.key ||| ((1 : UInt64) <<< 23 ) }
254+
255+ def ConfigWithKey.setTransparency (transparency : TransparencyMode) (c : ConfigWithKey) : ConfigWithKey :=
256+ { config := { c.config with transparency }
257+ key := ((c.key >>> (3 : UInt64)) <<< 3 ) ||| transparency.toUInt64 }
258+
233259/--
234260Function parameter information cache.
235261-/
@@ -494,25 +520,29 @@ structure Context where
494520 /-- Not `none` when inside of an `isDefEq` test. See `PostponedEntry`. -/
495521 defEqCtx? : Option DefEqContext := none
496522 /--
497- Track the number of nested `synthPending` invocations. Nested invocations can happen
498- when the type class resolution invokes `synthPending`.
523+ Track the number of nested `synthPending` invocations. Nested invocations can happen
524+ when the type class resolution invokes `synthPending`.
499525
500- Remark: `synthPending` fails if `synthPendingDepth > maxSynthPendingDepth`.
526+ Remark: `synthPending` fails if `synthPendingDepth > maxSynthPendingDepth`.
501527 -/
502528 synthPendingDepth : Nat := 0
503529 /--
504- A predicate to control whether a constant can be unfolded or not at `whnf`.
505- Note that we do not cache results at `whnf` when `canUnfold?` is not `none`. -/
506- canUnfold? : Option (Config → ConstantInfo → CoreM Bool) := none
530+ A predicate to control whether a constant can be unfolded or not at `whnf`.
531+ If set, overrides `Config.canUnfoldPredicateConfig`.
532+ Note that we do not cache results at `whnf` when `canUnfold?` is not `none`.
533+ This field lives outside `Config` because it is not cacheable and its type does not have a `Repr`
534+ instance.
535+ -/
536+ customCanUnfoldPredicate? : Option (Config → ConstantInfo → CoreM Bool) := none
507537 /--
508538 When `Config.univApprox := true`, this flag is set to `true` when there is no
509539 progress processing universe constraints.
510540 -/
511541 univApprox : Bool := false
512542 /--
513543 `inTypeClassResolution := true` when `isDefEq` is invoked at `tryResolve` in the type class
514- resolution module. We don't use `isDefEqProjDelta` when performing TC resolution due to performance issues.
515- This is not a great solution, but a proper solution would require a more sophisticated caching mechanism.
544+ resolution module. We don't use `isDefEqProjDelta` when performing TC resolution due to performance issues.
545+ This is not a great solution, but a proper solution would require a more sophisticated caching mechanism.
516546 -/
517547 inTypeClassResolution : Bool := false
518548 /--
@@ -1172,7 +1202,12 @@ def elimMVarDeps (xs : Array Expr) (e : Expr) (preserveOrder : Bool := false) :
11721202 { ctx with keyedConfig := { config } }
11731203
11741204@[inline] def withCanUnfoldPred (p : Config → ConstantInfo → CoreM Bool) : n α → n α :=
1175- mapMetaM <| withReader (fun ctx => { ctx with canUnfold? := p })
1205+ mapMetaM <| withReader (fun ctx => { ctx with customCanUnfoldPredicate? := some p })
1206+
1207+ @[inline] def withCanUnfoldAtMatcherPred : n α → n α :=
1208+ mapMetaM <| withReader (fun ctx => { ctx with
1209+ customCanUnfoldPredicate? := none,
1210+ keyedConfig := ctx.keyedConfig.withCanUnfoldAtMatcherPred })
11761211
11771212@[inline] def withIncSynthPending : n α → n α :=
11781213 mapMetaM <| withReader (fun ctx => { ctx with synthPendingDepth := ctx.synthPendingDepth + 1 })
@@ -1264,11 +1299,9 @@ def withTrackingZetaDeltaSet (s : FVarIdSet) : n α → n α :=
12641299@[inline] def withoutProofIrrelevance (x : n α) : n α :=
12651300 withConfig (fun cfg => { cfg with proofIrrelevance := false }) x
12661301
1267- @[inline] private def Context.setTransparency (ctx : Context) (transparency : TransparencyMode) : Context :=
1268- let config := { ctx.config with transparency }
1269- -- Recall that `transparency` is stored in the first 3 bits (it has 5 values).
1270- let key : UInt64 := ((ctx.configKey >>> (3 : UInt64)) <<< 3 ) ||| transparency.toUInt64
1271- { ctx with keyedConfig := { config, key } }
1302+ @[inline]
1303+ private def Context.setTransparency (ctx : Context) (transparency : TransparencyMode) : Context :=
1304+ { ctx with keyedConfig := ctx.keyedConfig.setTransparency transparency }
12721305
12731306@[inline] def withTransparency (mode : TransparencyMode) : n α → n α :=
12741307 -- We avoid `withConfig` for performance reasons.
0 commit comments