-
Notifications
You must be signed in to change notification settings - Fork 34
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
Discharge on the fly #72
Open
herbelin
wants to merge
1
commit into
coq:master
Choose a base branch
from
herbelin:discharge-on-the-fly
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
- Title: Discharge on the fly | ||
|
||
- Drivers: Hugo Herbelin | ||
|
||
---- | ||
|
||
# Summary | ||
|
||
After the refactoring of discharge made in coq/coq#14727, it becomes possible to discharge declarations at the time of their declaration. We discuss a proposal in this direction. | ||
|
||
# Motivation | ||
|
||
It is common in a section to want to temporarily generalize the notions defined in the section but to continue to work in the context of the section for further developments, as in: | ||
|
||
```coq | ||
Section S. | ||
Context {A B:Type}. | ||
Inductive option := None | Some (a:A). | ||
Definition map (f : A -> B) (o : option) := | ||
match o with | ||
| None => Top.None | ||
| Some a => Top.Some (f a) | ||
end. | ||
(* ... *) | ||
End S. | ||
``` | ||
|
||
This is what the proposal tends to achieve. | ||
|
||
# Details about the design | ||
|
||
## Basic idea | ||
|
||
The basic proposal is to emulate a section | ||
```coq | ||
Section S. | ||
Variable a : A. | ||
Definition f := ... | ||
``` | ||
as | ||
```coq | ||
Definition f a := ... | ||
Module S. | ||
Parameter a : A. | ||
Definition f := ... | ||
``` | ||
|
||
that is, that each persistent declaration of the section is declared both in the section and, discharged, at toplevel (as well as appropriately discharged in all intermediary section levels). | ||
|
||
The resulting full names are typically `Top.f` for the toplevel copy, and `Top.S.f` for the copy in the section (as well as `Top.S.T.f`, etc., if there are nested sections). | ||
|
||
At the end of the section, the module being built is discarded. | ||
|
||
The distributivity of declarations over section levels is obtained by maintaining one environment/state for each section level: | ||
- opening a section forks a new copy of the current environment/state for the section; this copy becomes the active one | ||
- extending a section content enriches simultaneously and hereditarily all section levels (i.e. `Definition f := t` adds `Top.f` to all section levels, `Top.S.f` to all section levels from level `Top.S`, `Top.S.T.f` to all section levels from level `Top.S.T`, etc.); there are however three kinds of declarations (see below) | ||
- closing a section drops the active copy of the environment/state and makes active the environment/state of the outer section (which itself growed since the fork) | ||
|
||
## Definitionally connecting the different copies | ||
|
||
Different strategies are possible to definitionally relate the different copies. | ||
|
||
- The body of the constant is in the fully discharged copy and each copy in a section takes the form: | ||
``` | ||
Definition f := Top.f a. | ||
``` | ||
|
||
How to evaluate the risk that the encoding surfaces too easily (e.g. when reducing), losing the advantages of reasoning in a section? | ||
|
||
- Each copy has a full copy of the body discharged accordingly to the level of section where it lives without the less generalized copy evaluating to the more generalized one. This provides convertibility of `Top.f a` and `Top.S.f` for transparent constants but not for opaque constants or inductive types. For opaque constants and inductive types, a possibility would be that the conversion algorithm takes into account a table of correspondences between `Top.f a` and `Top.S.f`. | ||
|
||
## Which authoritative definition? | ||
|
||
The pre-existing model gets the typability of the fully-discharged declarations by trusting the type-checking of the non-discharged declarations and trusting the discharge algorithm. | ||
|
||
From the moment all copies are generated at the same time, it would reduce the trusted type-checking basis of documents whose sections are closed to instead type the fully-discharged declaration (see @gares' [suggestion](https://github.com/coq/coq/pull/17888#issuecomment-1653536034)). The trust in the discharge algorithm would then serve only to trust the (volative) inner of the sections (via the claim that discharging correctly reverts specialization). | ||
|
||
## Three kinds of objects in sections | ||
|
||
In practice, relatively to sections, Coq objects are of three kinds: | ||
- volatile: meaningful only in the section it is declared: this is the case of `Variable`, `Hypothesis`, polymorphic universes, etc. | ||
- generalizable: meaningful in all section levels: this is the case of `Definition`, `Inductive`, `Axiom`, etc. | ||
- global: meaningful in the section-free level: this is the case of `Require`, monomorphic universes, etc. | ||
|
||
## Non-logical objects | ||
|
||
Implicit arguments, arguments scopes, arguments renamings, ... are attached to a constant and should a priori be present at each level. | ||
|
||
For tables, such as coercions, canonical projections, hints, instances, it is unclear what status to give to them. | ||
|
||
For instance, having only the generalized form of the coercions would lead to too general coercions whose arguments cannot be inferred. Keeping the less general copy is a priori the safest path for compatibility. Do we need more? | ||
|
||
# Compatibility issues | ||
|
||
The model adds new names. So, it can in theory introduces new name ambiguities and force to qualify more. | ||
|
||
The question of efficiency is also to study. In the minimalistic approach, it is only about moving discharging tasks currently done at the end of a section towards the place where the object is discharged. But keeping several copies of coercions, hints, etc. at all levels may possibly result in slowdowns for e.g. `auto` or type classes resolution. | ||
|
||
# The experiment of PR coq/coq#17888 | ||
|
||
At the time of writing, PR coq/coq#17888 does the following: | ||
- introduces a distinction between the three kinds of objects | ||
- build dynamically the contents of all section levels and inherit their contents from outer sections to inner sections, for both the logical environment and the non-logical state | ||
- "certify" the innermost declaration, but certifying instead the outermost would be easy | ||
- the different discharged copies of a declaration are distinct copies of the original copy (no explicit sharing, no convertibility between opaque constants and inductive types from different section levels) | ||
|
||
# Further questions | ||
|
||
The model would a priori supports declaring module variables in a section and discharging modules in sections into functors. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitional equality is not enough in practice, the various copies must also be identified in the following contexts:
Hint
Search
results(and I'm not sure how exhaustive is this list)
There are at least the two following ways to address this problem:
Declare Equivalent Keys
all the time and make sure it is taken into account by every relevant part of the system (and document it properly cf [Declare Equivalent Keys] should be documented coq#4551).Ideally, intermediate definitions should be discarded when exiting the section.
(Optionally, also, in the future, it would be nice if re-entering a named section could provide the same context and the same aliases....)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my experiences to provide simultaneously the non-discharged and discharged versions of a canonical key, I had several incompatibilities. Studying the reason of these incompatibilities might help to understand if there is a way to make it working, but that does not seem to be straightforward to support (see for instance the failure on mathcomp I got when the discharged versions of a canonical projection are also allowed to be used).
By identified, I guess you mean
eq_constr
-equal (alpha-convertible) vsconv
-equal. Is it that you think that it would help compatibility? In any case, I struggled in not breaking too much compatibility in coq/coq#17888. I'm a bit pessimistic about the room for manœuver that we have.I agree. And it is not impossible to do if we accept to keep the inside of sections in vo files. And, at worst, even if keeping the inner of sections in vo files happens to be too costly in size, we may also recompute dynamically the instances.
[In any case, thanks for your support!]