Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - refactor(tactic/lint/type_classes): change inhabited linter to nonempty linter #15542

Closed
wants to merge 10 commits into from

Conversation

kmill
Copy link
Collaborator

@kmill kmill commented Jul 20, 2022

The inhabited typeclass is intended to be a default value (and computable, if one is writing programs) but many times it is filled in with a junk (and perhaps noncomputable) value to satisfy the has_inhabited_instance linter. This commit switches to a has_nonempty_instance linter to push contributors toward supplying a nonempty instance instead. The linter still accepts inhabited and unique instances, which should be preferred over nonempty when appropriate.


Open in Gitpod

…ty linter

The `inhabited` typeclass is intended to be a default value (and computable, if one is programming) but many times it is filled in with a junk (and perhaps noncomputable) value to satisfy the inhabited linter. This switches to pushing contributors to supply a `nonempty` instance. The linter still accepts `inhabited` and `unique` instances.
@kmill kmill added awaiting-author A reviewer has asked the author a question or requested changes awaiting-CI The author would like to see what CI has to say before doing more work. labels Jul 20, 2022
@github-actions github-actions bot removed the awaiting-CI The author would like to see what CI has to say before doing more work. label Jul 20, 2022
Co-authored-by: Eric Wieser <wieser.eric@gmail.com>
@kmill kmill added awaiting-review The author would like community review of the PR awaiting-CI The author would like to see what CI has to say before doing more work. and removed awaiting-author A reviewer has asked the author a question or requested changes labels Jul 20, 2022
@github-actions github-actions bot removed the awaiting-CI The author would like to see what CI has to say before doing more work. label Jul 21, 2022
@kmill
Copy link
Collaborator Author

kmill commented Jul 21, 2022

#1898 is where the has_inhabited_instance linter was added, which had some discussion.

@gebner I think I still don't fully understand the inhabited instance linter, and it might be because the corners of mathlib I'm familiar with don't tend to need inhabited over nonempty. Maybe these are the goals:

  • if a definition needs a default value, you'd prefer to have a computable inhabited instance.
  • if that definition is noncomputable, it's ok to use nonempty and choice.
  • if a theorem needs a default value in a proof, nonempty is enough.

There are a number of places in mathlib where there are arbitrary values (like 37), or inhabited instances that require hard-to-meet additional typeclasses, or they're noncomputable. These all seem to subvert the goals of the linter, which is why I was thinking about changing it to a nonempty linter. But this might subvert the goals further since now people will write nonempty instances when inhabited instances might be preferred.

Maybe it would be better to have the linter itself suggest adding a nolint if there are no good default values? Or extend it to be satisfied with a nonempty instance (while keeping the has_inhabited_instance name) and document this somewhere?

@gebner
Copy link
Member

gebner commented Jul 22, 2022

My original intention with the inhabited linter was to flag issues like inhabited (array α) is missing (and there were a lot of such more-or-less clear-cut missing instances back in the day). I wanted to push people to add general instances like inhabited α → inhabited (additive α). The concrete motivation was an encoding to simply-typed higher-order logic, were types are required to be nonempty (and the encoding can be made simpler if we know that the Lean type is nonempty).

For many types in mathlib, requiring inhabited doesn't make much sense though (like morphism types, etc.) because there is no canonical or general instance. This is also reflected in the sheer number of @[nolint has_inhabited] attributes. For that reason, I proposed retiring the inhabited linter, since I thought it was just annoying people.

But to my surprise, some people actually took the linter's advice in an unexpected and different direction. Instead of adding general instances, they added particular examples of the type in the question (such as the 37 you refer to). This is certainly valuable information (and a sneaky way to get around mathlib's "no examples" policy), but not really what the inhabited type class is for. (I guess I should have just made the linter smarter.)

In general, making these noncanonical inhabitants nonempty rather than inhabited seems like a good change to me. Maybe we also need a more explicit and officially sanctioned way to include examples (I have no data on how common this abuse of inhabited is). There is one notable use of inhabited though, namely in the unique type class, so we can't just change everything to nonempty.

@fpvandoorn
Copy link
Member

I am personally more in favor of retiring this linter (and removing a bunch of inhabited instances that are never used), but I don't mind this change either.

@eric-wieser
Copy link
Member

I think pushing for nonempty instances is a good idea still; it forces users contributing new structures to avoid defining something that aliases false for every parametrization by accident.

Copy link
Collaborator

@Vierkantor Vierkantor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm enough of an intuitionist to think that we should push inhabited as much as possible, but I guess the consensus in this thread overrules me.

I'd still like the documentation to push the user a bit further towards inhabited or unique if appropriate, otherwise this looks good to me.

Could you merge master before handing the PR over to bors?

bors d+

src/tactic/lint/default.lean Outdated Show resolved Hide resolved
src/tactic/lint/type_classes.lean Outdated Show resolved Hide resolved
src/tactic/lint/type_classes.lean Outdated Show resolved Hide resolved
@bors
Copy link

bors bot commented Jul 29, 2022

✌️ kmill can now approve this pull request. To approve and merge a pull request, simply reply with bors r+. More detailed instructions are available here.

@kmill
Copy link
Collaborator Author

kmill commented Jul 30, 2022

bors r+

@github-actions github-actions bot added ready-to-merge All that is left is for bors to build and merge this PR. (Remember you need to say `bors r+`.) and removed awaiting-review The author would like community review of the PR labels Jul 30, 2022
bors bot pushed a commit that referenced this pull request Jul 30, 2022
…ty linter (#15542)

The `inhabited` typeclass is intended to be a default value (and computable, if one is writing programs) but many times it is filled in with a junk (and perhaps noncomputable) value to satisfy the `has_inhabited_instance` linter. This commit switches to a `has_nonempty_instance` linter to push contributors toward supplying a `nonempty` instance instead. The linter still accepts `inhabited` and `unique` instances, which should be preferred over `nonempty` when appropriate.
@bors
Copy link

bors bot commented Jul 30, 2022

Pull request successfully merged into master.

Build succeeded:

@bors bors bot changed the title refactor(tactic/lint/type_classes): change inhabited linter to nonempty linter [Merged by Bors] - refactor(tactic/lint/type_classes): change inhabited linter to nonempty linter Jul 30, 2022
@bors bors bot closed this Jul 30, 2022
@bors bors bot deleted the kmill_nonempty_linter branch July 30, 2022 09:03
@digama0
Copy link
Member

digama0 commented Jul 30, 2022

Why are there junk inhabited instances being made? I did see a 37 in one of them, but I think we should try to avoid that kind of thing. There should be an inhabited instance where applicable, and it should be canonical where possible.

bottine pushed a commit to bottine/mathlib that referenced this pull request Jul 30, 2022
…ty linter (leanprover-community#15542)

The `inhabited` typeclass is intended to be a default value (and computable, if one is writing programs) but many times it is filled in with a junk (and perhaps noncomputable) value to satisfy the `has_inhabited_instance` linter. This commit switches to a `has_nonempty_instance` linter to push contributors toward supplying a `nonempty` instance instead. The linter still accepts `inhabited` and `unique` instances, which should be preferred over `nonempty` when appropriate.
robertylewis pushed a commit that referenced this pull request Aug 2, 2022
…ty linter (#15542)

The `inhabited` typeclass is intended to be a default value (and computable, if one is writing programs) but many times it is filled in with a junk (and perhaps noncomputable) value to satisfy the `has_inhabited_instance` linter. This commit switches to a `has_nonempty_instance` linter to push contributors toward supplying a `nonempty` instance instead. The linter still accepts `inhabited` and `unique` instances, which should be preferred over `nonempty` when appropriate.
khwilson pushed a commit that referenced this pull request Aug 2, 2022
…ty linter (#15542)

The `inhabited` typeclass is intended to be a default value (and computable, if one is writing programs) but many times it is filled in with a junk (and perhaps noncomputable) value to satisfy the `has_inhabited_instance` linter. This commit switches to a `has_nonempty_instance` linter to push contributors toward supplying a `nonempty` instance instead. The linter still accepts `inhabited` and `unique` instances, which should be preferred over `nonempty` when appropriate.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ready-to-merge All that is left is for bors to build and merge this PR. (Remember you need to say `bors r+`.)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants