leanprover / leanprover/lean4

Handler for `deriving Inhabited` on private structure introduces public auxiliary definition

Open
#14,341 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug P-medium
Dominant language
Lean
Stars
9.2k
Forks
990
Avg merge
1d 17h
Merged PRs (30d)
175

Description

Prerequisites
Description

In a module, deriving Inhabited for a private structure produces a private instance, but the auxiliary definition holding the default value is not private. This is a regression in v4.31.0, likely introduced by the new handler for deriving Inhabited in #9815.

This bug causes problems downstream. For example, the linter in Batteries would complain that the (public) auxiliary definition doesn't have a doc string.

Context

I raised this on Zulip: #general > Missing doc string for `deriving Inhabited`.

Steps to Reproduce

Build the following file:

module

private structure A where
deriving Inhabited

/--
info: @[instance_reducible] private def instInhabitedA : Inhabited A :=
{ default := instInhabitedA.default }
-/
#guard_msgs in
#print instInhabitedA

/--
info: private def instInhabitedA.default : A :=
{ }
-/
#guard_msgs in
#print instInhabitedA.default

Expected behavior: Build succeeds with no messages.

Actual behavior: Build fails with error message:

❌️ Docstring on `#guard_msgs` does not match generated message:

- info: private def instInhabitedA.default : A :=
+ info: def instInhabitedA.default : A :=
  { }
Versions

Lean 4.33.0-nightly-2026-07-09
Target: x86_64-unknown-linux-gnu

Additional Information

None.

Impact

Add 👍 to issues you consider important. If others are impacted by this issue, please ask them to add 👍 to it.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by building the minimal module reproducer and compare the guarded output for the private structure's derived Inhabited instance and its default value. Then inspect the new deriving Inhabited handler introduced by #9815; done means the auxiliary default definition is private and the #guard_msgs checks succeed without messages.

Written by the indexing model from the issue text.

Assessment

Domain
compilers
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
65/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.