feat: have example default to the private scope (#10168)

This commit is contained in:
Sebastian Ullrich 2025-09-15 11:10:56 +02:00 committed by GitHub
parent d869c38e7b
commit 8df968de01
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 33 additions and 13 deletions

View file

@ -1189,7 +1189,10 @@ where
let tacPromises ← views.mapM fun _ => IO.Promise.new
let expandedDeclIds ← views.mapM fun view => withRef view.headerRef do
Term.expandDeclId (← getCurrNamespace) (← getLevelNames) view.declId view.modifiers
withExporting (isExporting := !expandedDeclIds.all (isPrivateName ·.declName)) do
withExporting (isExporting :=
-- `example`s are always private unless explicitly marked `public`
views.any (fun view => view.kind != .example || view.modifiers.isPublic) &&
expandedDeclIds.any (!isPrivateName ·.declName)) do
let headers ← elabHeaders views expandedDeclIds bodyPromises tacPromises
let headers ← levelMVarToParamHeaders views headers
if let (#[view], #[declId]) := (views, expandedDeclIds) then
@ -1278,7 +1281,7 @@ where
}
applyAttributesAt declId.declName view.modifiers.attrs .afterTypeChecking
applyAttributesAt declId.declName view.modifiers.attrs .afterCompilation
finishElab headers (isExporting := false) := withFunLocalDecls headers fun funFVars => do
finishElab headers := withFunLocalDecls headers fun funFVars => do
let env ← getEnv
if warn.exposeOnPrivate.get (← getOptions) then
if env.header.isModule && !env.isExporting then
@ -1288,15 +1291,13 @@ where
logWarningAt attr.stx m!"Redundant `[expose]` attribute, it is meaningful on public \
definitions only"
withExporting (isExporting :=
headers.any (fun header =>
header.modifiers.isInferredPublic env &&
!header.modifiers.isMeta &&
!header.modifiers.attrs.any (·.name == `no_expose)) &&
(isExporting ||
headers.all (fun header => (header.kind matches .abbrev | .instance)) ||
(headers.all (·.kind == .def) && sc.attrs.any (· matches `(attrInstance| expose))) ||
headers.any (·.modifiers.attrs.any (·.name == `expose)))) do
withoutExporting (when :=
headers.all (fun header =>
header.modifiers.isMeta ||
header.modifiers.attrs.any (·.name == `no_expose) ||
(!(header.kind == .def && sc.attrs.any (· matches `(attrInstance| expose))) &&
!header.modifiers.attrs.any (·.name == `expose) &&
!header.kind matches .abbrev | .instance))) do
let headers := headers.map fun header =>
{ header with modifiers.attrs := header.modifiers.attrs.filter (!·.name ∈ [`expose, `no_expose]) }
let values ← try

View file

@ -149,9 +149,13 @@ def isGenPattern? (pat : Expr) : Option (GenPatternInfo × Expr) :=
/-- Returns `true` if `declName` is the name of a `match`-expression congruence equation. -/
def isMatchCongrEqDeclName (declName : Name) : CoreM Bool := do
let declName := privateToUserName declName
match declName with
| .str p s => return (← isMatcher p) && Match.isCongrEqnReservedNameSuffix s
| .str p s =>
pure (Match.isCongrEqnReservedNameSuffix s) <&&>
-- `declName` was formed by `mkPrivateName _ matcherName` but as `matcherName` may or may not
-- have already been private, there is no direct way to invert this function; so we try both
-- possibilities (at most one of them can exist).
(isMatcher p <||> isMatcher (privateToUserName p))
| _ => return false
/-- Returns `true` if `e` is a constant for a `match`-expression congruence equation. -/

View file

@ -41,6 +41,20 @@ public theorem t : f = 1 := testSorry
/-- A private definition. -/
def fpriv := 1
public section
/-- Examples are always private. -/
example : fpriv = 1 := rfl
/--
error: Unknown identifier `fpriv`
Note: A private declaration `fpriv` (from the current module) exists but would need to be public to access here.
-/
#guard_msgs in
/-- ...unless explicitly marked `public`. -/
public example : fpriv = 1 := rfl
end
/--
error: Unknown identifier `fpriv`
@ -54,6 +68,7 @@ public class X
/-- A local instance of a public class. -/
instance : X := ⟨⟩
-- Check that the theorem types are checked in exported context, where `f` is not defeq to `1`
-- (but `fexp` is)