@@ -69,6 +69,27 @@ def isEqnReservedNameSuffix (s : String) : Bool :=
6969def unfoldThmSuffix := "eq_def"
7070def eqUnfoldThmSuffix := "eq_unfold"
7171
72+ def isEqnLikeSuffix (s : String) : Bool :=
73+ s == unfoldThmSuffix || s == eqUnfoldThmSuffix || isEqnReservedNameSuffix s
74+
75+ /--
76+ The equational theorem for a definition can be private even if the definition itself is not.
77+ So un-private the name here when looking for a declaratin
78+ -/
79+ def declFromEqLikeName (env : Environment) (name : Name) : Option (Name × String) := Id.run do
80+ if let .str p s := name then
81+ if isEqnLikeSuffix s then
82+ for p in [p, privateToUserName p] do
83+ if (env.setExporting false ).isSafeDefinition p && !isMatcherCore env p then
84+ return some (p, s)
85+ return none
86+
87+ def mkEqLikeNameFor (env : Environment) (declName : Name) (suffix : String) : Name :=
88+ let isExposed := !env.header.isModule || ((env.setExporting true ).find? declName).elim false (·.hasValue)
89+ let name := .str declName suffix
90+ let name := if isExposed then name else mkPrivateName env name
91+ name
92+
7293/--
7394Throw an error if names for equation theorems for `declName` are not available.
7495-/
@@ -82,14 +103,14 @@ def ensureEqnReservedNamesAvailable (declName : Name) : CoreM Unit := do
82103/--
83104Ensures that `f.eq_def`, `f.unfold` and `f.eq_<idx>` are reserved names if `f` is a safe definition.
84105-/
85- builtin_initialize registerReservedNamePredicate fun env n =>
86- match n with
87- | .str p s =>
88- (isEqnReservedNameSuffix s || s == unfoldThmSuffix || s == eqUnfoldThmSuffix)
89- && env.isSafeDefinition p
90- -- Remark: `f.match_<idx>.eq_<idx>` are handled separately in `Lean.Meta.Match.MatchEqs`.
91- && !isMatcherCore env p
92- | _ => false
106+ builtin_initialize registerReservedNamePredicate fun env n => Id.run do
107+ if let some (declName, suffix) := declFromEqLikeName env n then
108+ -- The reserved name predicate has to be precise, as `resolveExact`
109+ -- will believe it. So make sure that `n` is exactly the name we expect,
110+ -- including the privat prefix.
111+ n == mkEqLikeNameFor env declName suffix
112+ else
113+ false
93114
94115def GetEqnsFn := Name → MetaM (Option (Array Name))
95116
@@ -144,9 +165,9 @@ builtin_initialize eqnsExt : EnvExtension EqnsExtState ←
144165/--
145166Simple equation theorem for nonrecursive definitions.
146167-/
147- private def mkSimpleEqThm (declName : Name) (suffix := Name.mkSimple unfoldThmSuffix) : MetaM (Option Name) := do
168+ private def mkSimpleEqThm (declName : Name) : MetaM (Option Name) := do
148169 if let some (.defnInfo info) := (← getEnv).find? declName then
149- let name := declName ++ suffix
170+ let name := mkEqLikeNameFor (← getEnv) declName unfoldThmSuffix
150171 realizeConst declName name (doRealize name info)
151172 return some name
152173 else
@@ -271,28 +292,38 @@ By default, we do not create unfold theorems for nonrecursive definitions.
271292You can use `nonRec := true` to override this behavior.
272293-/
273294def getUnfoldEqnFor? (declName : Name) (nonRec := false ) : MetaM (Option Name) := withLCtx {} {} do
274- let env ← getEnv
275- let unfoldName := Name.str declName unfoldThmSuffix
276- if env.contains unfoldName then
277- return some unfoldName
278- if (← shouldGenerateEqnThms declName) then
279- for f in (← getUnfoldEqnFnsRef.get) do
280- if let some r ← f declName then
281- unless r == unfoldName do
282- throwError "invalid unfold theorem name `{r}` has been generated expected `{unfoldName}`"
283- return some r
284- if nonRec then
285- return (← mkSimpleEqThm declName)
286- return none
295+ withoutExporting do
296+ let env := (← getEnv)
297+ let unfoldName := mkEqLikeNameFor (← getEnv) declName unfoldThmSuffix
298+
299+ -- Search in the name space of the defininig module, can happen with `import all`.
300+ -- TODO: Should we always use `mkPrivateName` with as if we are in that module
301+ -- for realizable names?
302+ if let some mod ← findModuleOf? declName then
303+ let unfoldName' := mkPrivateNameCore mod (privateToUserName unfoldName)
304+ if env.contains unfoldName' then
305+ return some unfoldName'
306+
307+ if env.contains unfoldName then
308+ return some unfoldName
309+ if (← shouldGenerateEqnThms declName) then
310+ for f in (← getUnfoldEqnFnsRef.get) do
311+ if let some r ← f declName then
312+ unless r == unfoldName do
313+ throwError "invalid unfold theorem name `{r}` has been generated expected `{unfoldName}`"
314+ return some r
315+ if nonRec then
316+ return (← mkSimpleEqThm declName)
317+ return none
287318
288319builtin_initialize
289320 registerReservedNameAction fun name => do
290- let .str p s := name | return false
291- unless (← getEnv).isSafeDefinition p && !isMatcherCore (← getEnv) p do return false
292- if isEqnReservedNameSuffix s then
293- return (← MetaM.run' <| getEqnsFor? p ).isSome
294- if s == unfoldThmSuffix then
295- return (← MetaM.run' <| getUnfoldEqnFor? p (nonRec := true )).isSome
321+ if let some (declName, suffix) := declFromEqLikeName (← getEnv) name then
322+ if name == mkEqLikeNameFor (← getEnv) declName suffix then
323+ if isEqnReservedNameSuffix suffix then
324+ return (← MetaM.run' <| getEqnsFor? declName ).isSome
325+ if suffix == unfoldThmSuffix then
326+ return (← MetaM.run' <| getUnfoldEqnFor? declName (nonRec := true )).isSome
296327 return false
297328
298329end Lean.Meta
0 commit comments