Notes on side effects, universes and proof closing - coq/coq GitHub Wiki
In the hope of someday figuring out how to avoid universe double declarations and maybe even simplify close_proof.
NB: this is using https://github.com/coq/coq/pull/10863 otherwise the universe state is even more complicated since we have to consider the seff_univs in the ustate separately
Consider a monomorphic constant with a side effect:
Set Printing Universes.
Lemma foo : Type(*u*).
Proof.
abstract (exact Type(*v, v < u*)).
(* abstract declares foo_subproof with u,v |= v < u. u is removed from foo's ustate *)
Qed.
(**
We look at Proof_global.close_proof and Declare.add_constant for foo
(the subproof is always the same and boring as explained above)
##### Defined any mode, or Qed normal mode (coqc, coqtop)
Proof_global.close_proof: we have poly=false, now=true, keep_body_ucst_separate=false
Because there are side effects we are in the allow_deferred=true branch
return ({u},typ),((body,{} |= v < u),eff)
NB: if side_effects didn't put us in allow_deferred=true,
we would declare no typ univs which is broken in the Qed case
- if Defined:
Declare.ml calls export_private_constants (declare side effects (u,v |= u < v declared))
Declare.ml calls add_constant (def entry has no seff)
Term_typing: locally add typ univs {u} (double declaration!)
check typ, check body
Safe_typing: add_field: add typ univs {u} (double declaration!)
done
- if Qed:
Declare.ml calls add_constant
Safe_typing: add_constant
Term_typing:
locally add typ univs {u}
check typ
handle (inline) side effects -> add side effect univs to body univs
locally add body univs {u,v} |= v < u (double declaration for u!)
check body (skipping inlined seff)
save updated body univs in PrivateMonomorphic
add_field: add typ univs {u}
peek on body: it's forced:
add updated body univs {u,v} |= v < u (double declaration for u!)
##### Qed -async mode (coqide, coqc -async-proofs on)
close_proof with yet-to-do proof: now=false, keep_body_ucst_separate=true
(from stm.ml closse_future_proof in reach `Qed branch)
now=false -> delayed body branch
return ({u},typ),future ((body,{} |= v < u), eff)
Safe_typing add_constant:
Term_typing:
locally add typ univs {u}
check typ
wait for body
add_field: add typ univs {u}
peek on body: Later
whenever the proof finishes: (this is in the worker)
close_future_proof from stm.ml perform_buildp:
now=false, keep_body_ucst_separate=true, future is from_val
now=false so delayed branch of close_proof same as above
still perform_buildp:
we do the add_constant round with a forced future -> just like the normal mode
on join (coqide button, coqc -async)
Global.join() joins the futures from the original add_constant
kernel sees the same stuff as normal mode, but delayed body and an extra time in the worker
double check to get early errors, see aeb5daa2efdb2d0f2c75670e11d409f24528c54a
##### Qed vio and vio2vo mode
coqc -quick step:
delayed close_proof and Safe_typing.add_constant as -async mode, but the future will never run
save the proof closure separately in the .vio
vio2vo step:
close_proof from stm.ml check_task_aux with now=true, keep_body_ucst_separate=true
because there are side effects this is the same as the normal mode close_proof
send to kernel (sees the same as normal mode, all forced)
grab body and body univs from opaque table to save in vo
*)
Things to understand:
- what is the 3rd branch of close_proof for (case
(poly && not opaque) || (now && not keep_body_ucst_separate && no side effects)
), thepoly && not opaque
part is relatively clear but why is it needed for monomorphics? Maybe related to https://github.com/coq/coq/issues/10890 - why can't we replace the allow_deferred branch with the really delayed branch?
It may be useful to write up what happens when we do exact Type.
without abstract
ie no side effect case.