Here, we document the accompanying artifact for PLDI '22 Submission 145: _A Flexible Type System for Fearless Concurrency_. This artifact is a typechecker for the language described in that paper. It includes a parser for that language, implemented in "coq/ocaml/parser.mly", an inference engine for generating the non-syntax-directed elements of our typing derivations, implemented in "coq/ocaml/prover.ml", and a coq-verified typechecker for typing derivations, implemented in "coq/ImplVerifier.v". In the following sections, we describe the interface between these components, their individual functionalities, and how to use the compiled system. KICKING THE TIRES: We assume you are looking at the pldi_code_submission directory, easily linked from our VM and uploaded as an individual tarball for VM-free exploration as well. The `docs` directory here contains three files: `submission.pdf` is the submitted version of our paper. `appendix.pdf` is the appendix to our paper, which contains the paper proofs of progress and preservation, and some other key documentation of complicated points of our system such as extended function syntax, pinning and virtual transformation inference. `artifact-docs.pdf` is the documentation for this artifact. It explains how to build and run the artifact, how to interpret its error messages, and how key internal features work. We include the most salient points from the documentation here: Run `make` in the directory `coq/ocaml` to generate the executable `run`. This requires at least 10gb of RAM - MAKE SURE THIS IS AVAILABLE. This executable can then be run as follows: `./run -i gall_files/.gall` There is a -v option to obtain verbose output in the event of inference errors. In the event of typing errors, the verifier will output an error line number. Search the file `coq/ImplVerifier.v` for `(err_ln )` to find the source of error `n`, which will correspond exactly to some premise of a rule. The Coq implementations of our typing rules are found in coq/ImplVerifier.v The script `coq/ocaml/run_working.sh` will run all of our written tests. Please run it from within the directory `coq/ocaml`. STEP-BY-STEP GUIDE To evaluate the functionality of this artifact, we recommend the reviewers inspect our included test files to confirm that they are valid, well-typed Gallifrey programs. We then suggest that the reviewers edit these files, introducing errors that our type checker catches and explains. Reviewers should also feel free to write their own Gallifrey programs, and run the type checker on them. Using the Artifact To use the artifact, it must first be compiled, a process described in ``Compiling and Running the Artifact'' below. Then, you may either run a script that will typecheck a collection of provided example files, or write your own files. To write your own files will require an understanding of the parser, the OCaml inference engine, and the Gallina type-checker. In the remainder of this section, we provide a high-level overview of these components. Following sections delve into greater detail on each. Note that in the following, we specify paths fully from the root of the artifact directory, "~/pldi_code_submission/" in the VM. Also, should the reviewers need it, the VM password is "sandiego" Compiling and Running the Artifact Ensure you are in some subdirectory of pldi_code_submission which contains a Makefile. Run make. This will produce the file "coq/ocaml/run". Make will run several invocations of coqc, ocamlc, and extraction; the step "coqc ../ImplVerifier.v" is expected to take 15-20 min and consume 8-10gb of RAM. _Make sure that you have at least 10gb of RAM available before trying to run "make" for the first time_. During the Coq extraction process, warnings will indicate that logical axioms were encountered. This means that the correctness of the Coq verification of the Gallina source in "coq/ImplVerifier.v" is dependent on the truth of several propositions that we did not provide proof for. This is not an issue, as each of these propositions is a statement about the behavior of OCaml objects, namely the reflexivity, transitivity, and symmetry of OCaml equality, that we can safely assume but not prove with Coq. Once the file "run" is generated, it can be executed as "./run -i " on any source file "input_file" in our language. Examples are given in the directory "coq/ocaml/gall_files". To run the typechecker on each file in that directory, run the script "coq/ocaml/run_working.sh". This script can be used to verify that each of the example programs in that directory, from which the examples in the paper are sourced, do indeed typecheck in our language. To assist with modification of these, or synthesis of fresh examples, we provide the following guidance on the behavior of the implemented Parser and Typechecker. For illustrative purposes, we will provide mistakes that could have been made in the implementation of the following well-typed function "new_sll", and how to identify and fix them. 10: def new_sll() : sll { 11: let l = new sll; 12: l.head = none sll_node; 13: l 14: } Resolving Parser Errors The included PDF (in section ``Specification of the Parser'') provides a detailed list of the constructs accepted by the parser. In the event that a source file provided to "run" does not adhere to the grammar, an error such as: Fatal error: exception Prover.ProverType.IO.ParseError("Parse Error in input at token 'l' read at [12:4, 12:5)") will be thrown. This error in particular was caused by the following code, which is missing a semi-colon on line 11: 10: def new_sll() : sll { 11: let l = new sll 12: l.head = none sll_node; 13: l 14: } This demonstrates that the error messages are thrown at the point that the parser encounters a token that proves the provided source file is not in the grammar. Here, that token was the "l" on line 12 without a preceding semicolon. The messages will provide the text, start position, and end position of this token. Resolving OCaml Inference Errors Typing derivations rely heavily on the presence of the TS structural rules, which are not syntax-directed. The job of the OCaml codebase is to infer when these rules should apply, elaborated on in the included PDF. If it cannot determine applicable rules, the following error will be thrown: Fatal error: exception Prover.InferenceFailure This particular error was caused by the following code 10: def new_sll() : sll { 11: let l = new sll; 12: l.head = none sll_node; 13: send-node(l.head); 14: l 15: } Here, since the target of the pointer "l.head" was sent away before the function returns, but the function expects "l" to be in a ``simple'' state with no explored fields, there is no typing derivation for this function, and the OCaml inference engine will fail. To help debug such cases, the cause for the inference failure is also output. For this example, the following was also reported to the user: Inference FAILED on goal 'new_sll' with reason: [ could not eliminate l as a tracked variable, unfocus and drop both failed: --Unfocus failed for reason: [ attempt_unfocus l: inference failed for reason: [ inference required retracting the field head rooted at l, which failed for reason: [ attempt_retract l.head: inference failed for reason: [ IMPOSSIBILITY: the target region r2 of the tracked reference l.head is untracked, and so retraction is impossible]]]]; --Drop failed for reason: [ cannot drop l's regions because it is the overall type of the declare] ] This error message attempts to communicate the fact that, at the end of the function, the prover encountered the typing context ℋ = r₁⟨l[head ↣ r₂]⟩ but did not expect l to be focused. The two strategies it tried to employ to unfocus l were to "unfocus" it directly and to "drop" its region. The direct "unfocus" failed because it would've first required a "retract", which in turn required the target region r₂ to be tracked, which it is not. The "drop" failed because the region of l, r₁, is the region of the value returned at the end of the function's outermost inner scope. In general, these error messages are a work-in-progress; we have found that they are an essential aid in debugging inference failures, but understand that they may be opaque. The authors would like to encourage the reviewers to reach out to us via HOTCRP (or any other medium) should these errors prove too cryptic. Resolving Gallina Verification Errors The OCaml prover only performs as much typechecking as is necessary to complete inference, so many type errors will not be caught until the prover's candidate typing derivation is passed to the verifier. For example, consider the following alteration to "new_sll": 10: def new_sll() : sll { 11: let l = new sll; 12: l.head = none sll_node; 13: send-node(l.head); 14: l 15: } This will cause the following error to be thrown: Verifier could not derive a premise that was assumed by the passed derivation, and needed for well-typedness. The message here will always be the same, as the primary output from the Gallina verifier is just a certificate of well-typedness for the whole program or lack thereof, but the two following fields aid debugging by indicating which function's typing derivation in particular could not be verified, and which premise of a typing rule in particular did not hold. These premises can be identified by their unique numbering in the file "coq/ImplVerifier.v". For further details on this process, see the included PDF.