I am trying to implement opaque constants (something akin to Lemma foo := bar.
) and I am a bit confused by the code in Declare
. I don't understand if this can be performed with one of the existing constructors (i.e., ConstantEntry
and OpaqueEntry
) or if I need a third case.
It should work with the existing ones
So, which one?
Doesn't Declare.declare_definition ~opaque:true
do what you want?
No, it dies on the assert false
in Declare.cast_opaque_proof_entry
.
One of the things I don't understand is why proof_entry_type
is an option and when it stops being None
. (It has to stop at some point, right? Because every entry has a type, doesn't it?)
I think in some cases it was inferred
But that code is indeed quite tricky let's wait for @Pierre-Marie Pédrot who is the cast wizard
When doing Definition foo := bar
, proof_entry_type
is None
. So, when I transpose the code to Lemma foo := bar
, the assertion fails because it is still None
. And I don't understand when it is supposed to stop being None
for Definition foo := bar
.
Ok, I think I remember now.
For opaque proof entries, the kernel is not allowed to look into the term
as it could be delayed, so providing the type is mandatory
So the current API disallows #[opaque] Definition foo := bar.
as-is
I don't know if that makes sense, but it is what it is
Note that the kernel accepts that due to the type of Entries.type definition_entry
I mean, it allows for the type to be absent, but not in the case there may not a body
@Guillaume Melquiond does it make sense?
That's really due to the way the kernel API is
I'm sure it can be improved
Sure, I understand why the type is mandatory for opaque entries. But I don't understand how the code can get away with transparent entries not having a type.
The kernel doesn't require it, and will infer the type
See Entries.definition_entry
that's a kernel API
type definition_entry = {
const_entry_body : constr;
(* List of section variables *)
const_entry_secctx : Id.Set.t option;
const_entry_type : types option;
const_entry_universes : universes_entry;
const_entry_inline_code : bool;
}
however, in this case, the body is mandatory
But, when you do About foo
, the kernel does not infer the type on the fly, does it? So, the type is already there somewhere. But I don't understand where.
yes, Entries.definition_entry
is the _input_ to the kernel
the kernel will infer the type and store it
yes it does infer it on the fly, _when_ declaring the constant
or if you specify the type, the kernel will infer, and compare with the provided one
that's how the kernel works basically I understand
it doesn't implement bi-directional TC
the type is stored in the environment
Declarations.pconstant_body
It took me a while to realize which types are input and what types are output
I'm sure we could improve the terminology here
tho once you know it, kind of makes sense
I guess
Does it make sense @Guillaume Melquiond ?
Yes. But what about my original question? Can it be done with one of the two existing constructors or do I need to add a third one?
I see that the kernel has Safe_typing.translate_direct_opaque
. So, the kernel actually already supports Lemma foo := bar
. I just need a way to invoke it.
I would try to avoid adding a new constructor
but I'm not sure if it can be done
Don't use translate_direct_opaque, this is side-effect specific stuff
That's internal actually, I got confused because I thought you were talking about Declare
, but you are actually talking about the constructors in Safe_typing
use the Declare primitives to infer the type of the opaque definition, and send that to the kernel
the kernel should treat any opaque stuff as an axiom
there is a bit of unfortunate coupling between the various entries
Pierre-Marie Pédrot said:
use the Declare primitives to infer the type of the opaque definition, and send that to the kernel
Do you have something specific in mind? Because I have been staring at Declare
for two weeks now and I don't see anything that could help here.
Declare does not indeed infer types
some examples of code doing that may be in vernac
in https://github.com/coq/coq/blob/aa0d53369c40ceab7a31e7a1abf602efc7f00bc2/vernac/comDefinition.ml#L99-L100 when it's opaque call interp_constr_evars_impls_ty
(you will need to add this function, behaving as interp_constr_evars_impls but also returning the type, kinda annoying to do as all the Constrintern.interp_* functions use Pretyping.understand_* variants that drop the type instead of eg understand_tcc_ty which returns it, but shouldn't be difficult)
NB only when it's opaque as giving the type to the kernel has perf cost so shouldn't be done when not needed
Last updated: Dec 05 2023 at 05:01 UTC