Skip to content

Cleaning flags - #49

Open
yannilefki wants to merge 10 commits into
mainfrom
cleaning_flags
Open

Cleaning flags#49
yannilefki wants to merge 10 commits into
mainfrom
cleaning_flags

Conversation

@yannilefki

Copy link
Copy Markdown
Collaborator

Added new flag policy, and cleaned code along the way.
I did my best to correct any bug I created, but this cleaning is far from bugproof, so I believe it is important to clean incrementally (that is : comment during the first pass, a.k.a this PR, then delete when coming on the code later on, with more experience on the usage of the new flags/the meaning of the past flag policies).

Comment on lines +321 to +323
(* Yanni : Deprecated flag *)
mutable step_typechecking_mode : Flags.typechecking_mode;
(* mutable step_flag_check_validity : bool; (* state of flag check_validity at start; must be the same at end *) *)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I assume line 323 is deprecated, not 322 ?

Comment thread lib/framework/flags.ml
Comment on lines +169 to +172
type typechecking_mode =
| Unverified (* equivalent to `resource_typing_enabled = false && check_validity = false` *)
| Annotated (* equivalent to `check_validity = false` *)
| AnnotatedAndVerified (* equivalent to `check_validity := true && preserve_specs_only = false` *)

@Bastacyclop Bastacyclop Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'd suggest describing their semantics independently from the previous flags so that the description stands on its own. Especially since the semantics of the previous flags was unclear, and we will delete them.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

For example, Unverified should be closer to resource_typing_enabled = false && check_validity = true in my opinion, in the sense that while the code is not verified and has no annotations, we are in this mode responsible for applying semantics-preserving transformations (not relative to the spec, but relative to the code itself).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Alternative naming option going through my head:

  • Unverified --> SemanticsPreserving, we do not have specifications and proofs, so no annotations, therefore the code stands as its own specification and we must ensure that we preserve its semantics
  • AnnotatedAndVerified --> ProofPreserving, we have specifications and proofs in the form of annotations and we are responsible for preserving them so that typechecking can still verify the code against them
  • Annotated --> ProofRepairing, we have specifications and proofs in the form of annotations and we are in the process of repairing the proof, so typechecking might not be able to verify the code right now, but we promise to go back to ProofPreserving at some point.

The first name matches the standard notion of semantics-preserving transformations.
The second names matches the OptiTrust notion of proof-preserving transformations (not a new notion but had different names in prior work).
The third name matches the standard notion of proof repair where the tool is being guided towards from a broken proof to a fixed proof.

Comment on lines +139 to 148
(* TODO : depreciate transformation *)
(** [clear_nosimpl tg]: clears all the marks on all the instructions that where
skipped by the simplifier *)
let%transfo clear_nosimpl (tg : target) : unit =
Marks.remove Arith_core.mark_nosimpl [nbMulti; cMark Arith_core.mark_nosimpl]

(* TODO : depreciate transformation *)
(** [nosimplf tg]: mark all the instructions targeted by [tg] as "__arith_core_nosimpl" *)
let%transfo nosimpl (tg : target) : unit =
Marks.add Arith_core.mark_nosimpl tg

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

these look like they should still work in all modes, they're just putting marks, so deprecation might not be needed.

Comment thread lib/transfo/gpu_basic.ml
Comment on lines +455 to 457
(* TODO : depreciate transformation *)
let%transfo insert_barrier (tg: target) =
Sequence_basic.insert ~reparse:false (magic_barrier ()) tg

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I wouldn't deprecate this one.

Comment thread lib/transfo/gpu.ml
let%transfo convert_tail_thread_for (loops : int list) (leaf: target) =
let fission_helper tg =
Flags.with_flag Flags.check_validity true (fun () -> Loop.fission tg) in
Flags.with_flag (* Flags.check_validity true *) Flags.typechecking_mode Flags.AnnotatedAndVerified (fun () -> Loop.fission tg) in

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

There's an interested question here : if we set the flag to verified, do we expect the code to be verifiable in the sense that typechecking should succeed, or do we expect the code to be verified in the sense that typechecking did run successfully and that the type information fields are up to date ?

Comment thread lib/transfo/if_basic.ml
trm_fail cond "condition is not pure, more advanced checks not yet supported"
end;
end; *)
Target.reparse_after ~reparse (Target.apply_at_target_paths (insert_on cond mark mark_then mark_else else_branch)) tg

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

note that reparse_after should also be deprecated : it is used when the user might insert arbitrary plain text code that requires reparsing into a proper AST ; ideally we don't need this anymore or find a way to do this locally without reparsing the entire program.

Comment thread lib/transfo/loop.ml
let loop_mark = next_mark () in
Loop_basic.move_out ~loop_mark [cPath seq_path; Constr_depth (DepthAt 0); tSpan [tFirst] [cMarkSpanStop mark_moved]];
if !Flags.check_validity then Resources.loop_minimize [cMark loop_mark];
if (* !Flags.check_validity *) Flags.annotated () then Resources.loop_minimize [cMark loop_mark];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'm not sure loop minimization makes any sense if the types are not up to date, I remember it to be driven by the typing fields that need to be up-to-date. Some of these might need strengthening to "verified".

Comment thread lib/transfo/loop_swap.ml
into:

// stars_j R(j) * V
// stars_j

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

?

open Prelude

let _ = Flags.check_validity := true
let _ = Flags.typechecking_mode := Flags.AnnotatedAndVerified

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Note that the specifications in this test don't mention values. When setting annotated and verified, specifications should probably mention values, otherwise the program is under-specified and many transformations will succeed while they probably shouldn't.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

alternative: accept weakening the test to the weaker specification

let _ = Flags.check_validity := true
(* let _ = Flags.check_validity := true *)
let _ = Flags.typechecking_mode := Flags.AnnotatedAndVerified
let _ = Flags.use_resources_with_models := true

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I believe this flag should also be deprecated.


let _ = Flags.check_validity := true
(* let _ = Flags.check_validity := true *)
let _ = Flags.typechecking_mode := Flags.AnnotatedAndVerified

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

this test was probably not designed for full functional verification.

@@ -1,7 +1,8 @@
(* Deprecated *)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

this one should work ?

@@ -1,7 +1,8 @@
(* Deprecated *)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think this test should work with validity checks but without using resource annotations ?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

this is also used in the unverified cleanup transformation

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Since we have a _models variant, we probably want to promote loop_reorder_at_models.ml into loop_reorder_at.ml. Then either we override this file, effectively removing one test, or we demote this file into something like loop_reorder_at_novalues.ml : we can still typecheck the transformation but against under-specified semantics where changing the computed values is not considered wrong (this can still be useful if you only want to check the absence of race conditions in Rust-style for example, some people actually asked me about that usage scenario at events).

@@ -1,8 +1,9 @@
(* Deprecated *)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

we use this in the unverified cleanup, so should probably be re-enabled before merging.

@@ -1,7 +1,8 @@
(* Deprecated *)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

used in unverified cleanup


let _ = Flags.check_validity := true
(* let _ = Flags.check_validity := true *)
let _ = Flags.use_resources_with_models := true

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

this flag should not be set anymore ?

let _ = Flags.use_resources_with_models := true
let _ = Flags.preserve_specs_only := true
(* let _ = Flags.preserve_specs_only := true *)
let _ = Flags.typechecking_mode := Flags.Annotated

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

AndVerified ?

!! Ghost.flatten_expr_rewrites (sum_tg @ [dRHS]);
!! replace_with_tree_reduce (trm_int log_tpb) sum_tg;
!! Flags.with_flag Flags.check_validity false (fun () -> Function.inline_def [cFunDef "tree_reduce"]);
!! Flags.with_flag (* Flags.check_validity false *) Flags.typechecking_mode Flags.Unverified (fun () -> Function.inline_def [cFunDef "tree_reduce"]);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

should this not still be Annotated mode ?

Comment on lines +884 to +889
(* Yanni : might change this flag to [Flags.Annotated] instead *)
(** [without_substep_validity_checks f] executes [f] with
the flag [check_validity] temporarily set to false.
Only for internal use; user scripts should use the [trustme] function. *)
let without_substep_validity_checks (f: unit -> 'a): 'a =
Flags.with_flag Flags.check_validity false f
Flags.with_flag (* Flags.check_validity false *) Flags.typechecking_mode Flags.Unverified f

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'd suggest renaming this function and checking all call sites for the intended semantics (multiple call sites may disagree on what they want).

(* Check that [Flags.check_validity] is like at the start of the step *)
if not on_error && (!Flags.check_validity && (not !Flags.use_resources_with_models)) <> infos.step_flag_check_validity
if not on_error && (!Flags.typechecking_mode <> infos.step_typechecking_mode) (* (!Flags.check_validity && (not !Flags.use_resources_with_models)) <> infos.step_flag_check_validity *)
then raise (TraceFailure "At finalize_step, Flags.check_validity is not same as when step was opened.");

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

  1. need to update the failure message
  2. how does that work with transformations like unverified cleanup that transition from one mode to another ?

let resource_error_expected (f: unit -> unit): unit =
failure_expected (function
| Resource_computation.ResourceError _ -> true
| _ -> false) (fun () -> f (); recompute_resources ())

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think we have Resources.ensure_computed () which is potentially cheaper (avoid duplicated triggers).

Comment thread lib/framework/flags.ml
let dump_ast_details : bool ref = ref false

(* TODO : deprecate once optilambda surface display works *)
(* TODO Yanni : deprecate once optilambda surface display works *)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

we can deprecate right now and incrementally improve the optilambda display to fit our needs

Comment on lines 14 to +17
let justif_correct (why : string) : unit =
if !Flags.check_validity then begin
ensure_computed ();
Trace.justif (sprintf "resources are correct: %s" why)
end
(* if !Flags.check_validity then begin *)
if Flags.annotated () then ensure_computed ();
Trace.justif (sprintf "resources are correct: %s" why)

@Bastacyclop Bastacyclop Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'd say this is only useful in Unverified/SemanticsPreserving mode, where there is no self-certifying proof. Calling it in another mode should trigger a warning.

Comment on lines +188 to 189
let (unfolds, folds) = if (* !Flags.check_validity *) Flags.annotated () then begin
let (res_start, res_stop) = Resources.around_instrs span_instrs in

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Ideally, reading any kind of computed resource information should not be allowed if they are not up-to-date. This means that this code should fail if not in AnnotatedAndVerified/ProofPreserving.

@Bastacyclop Bastacyclop left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looks like nice progress. Some thoughts:

  • We have too many deprecated tests, we should take the time to add models mentioning values for a bunch of them, we may also alternatively try running the verified mode on weaker models that don't constrain values : it is a weaker test than semantic preservation but still better than nothing.
  • We have many deprecated transformations, but a lot of them would probably be worth updating to the new modes. We should make it clear that this wave of deprecation does not mean "you shouldn't use this transformation anymore", but rather "you should reimplement this transformation before using it, or truly deprecate it if you have a better API".
  • In terms of short-term priority to counter-act all of this deprecation, I think we need to enforce the following before merging and going forward: every non-deprecated transformation should have a working non-deprecated unit test (including a trivial _doc test), ideally proof-preserving models mentioning values, possibly proof-preserving weaker models not mentioning values, possibly semantics-preserving without annotations/proof.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants