From 9fc2b42175b837f365b90f95d170f4c18fd8dafb Mon Sep 17 00:00:00 2001 From: jgabry Date: Thu, 17 Sep 2026 18:05:40 -0600 Subject: [PATCH 1/2] Rename the build record's fields and the code around them Nothing has shipped, so the names can still change. The record's `request` is now `configuration`, with `cpp_options`, `stanc_options`, `stanc_options_added` and `stanc_options_from_make` inside it, since cmdstanr injects nothing into `cpp_options` and the plain names mean what the arguments mean. `artifact` is `executable_hash`, `builder` is `cmdstan`, `known_untracked_dependencies` is `untracked_dependencies`, and the reason for a record that does not match its executable is `executable_mismatch`. The public result's `provenance` becomes `record`. The code follows: `read_current_build()` replaces `observe_build()`, `assess_build()` takes what is wanted and what is current, `stancflags_added_by_make()` replaces `inherited_stancflags()`, and the facts a model keeps about its executable come from `facts_from_record()`. Comments and test titles drop the design doc's vocabulary where it named these things. Part of #1258. --- R/build.R | 171 ++++++++++---------- R/build_record.R | 104 ++++++------ R/model.R | 49 +++--- dev-notes/compilation-state-contract.md | 112 ++++++------- dev-notes/compilation-state.md | 174 ++++++++++----------- tests/testthat/helper-build-record.R | 24 +-- tests/testthat/helper-envvars-and-paths.R | 5 +- tests/testthat/test-build-assess.R | 74 ++++----- tests/testthat/test-build-record-compile.R | 33 ++-- tests/testthat/test-build-record.R | 94 +++++------ tests/testthat/test-model-guard.R | 34 ++-- tests/testthat/test-model-rebuild-rules.R | 19 ++- tests/testthat/test-model-rebuild.R | 20 +-- tests/testthat/test-utils.R | 4 +- tests/testthat/testthat-problems.rds | Bin 0 -> 247499 bytes 15 files changed, 469 insertions(+), 448 deletions(-) create mode 100644 tests/testthat/testthat-problems.rds diff --git a/R/build.R b/R/build.R index 97e36ae20..86bec314f 100644 --- a/R/build.R +++ b/R/build.R @@ -3,12 +3,12 @@ #' Build or verify the executable for a Stan program #' -#' The one build path. The call is resolved into the request the record +#' The one build path. The call is resolved into the configuration the record #' compares, assess_build() says whether the executable beside the program (or #' in `dir`) was built from it, and a rebuild follows when it was not or when #' `force_recompile` asks for one. Both ways out generate the model's C++ from #' the source just verified or built, so a model constructed on a reused -#' executable holds the same snapshot as one that built it. +#' executable holds the same facts as one that built it. #' #' `force_recompile = NULL` means the caller did not say and the #' `cmdstanr_force_recompile` option decides. The rebuild reason names @@ -48,25 +48,25 @@ build_executable <- function(stan_file, # Options cmdstanr adds stay apart from the caller's, so the record can hold # each as it was, and are merged only when they become arguments. - injected <- list() + added <- list() if (pedantic) { - injected[["warn-pedantic"]] <- TRUE + added[["warn-pedantic"]] <- TRUE } if (isTRUE(cpp_option_value(cpp_options, "stan_opencl"))) { - injected[["use-opencl"]] <- TRUE + added[["use-opencl"]] <- TRUE } if (!is.null(user_header)) { - injected[["allow-undefined"]] <- TRUE + added[["allow-undefined"]] <- TRUE } - injected[["name"]] <- paste0(model_name_from_path(stan_file), "_model") + added[["name"]] <- paste0(model_name_from_path(stan_file), "_model") if (!stanc_option_supplied(stanc_options, "filename-in-msg")) { - injected[["filename-in-msg"]] <- wsl_safe_path(stan_file) + added[["filename-in-msg"]] <- wsl_safe_path(stan_file) } - request <- list( - cpp_options_supplied = parsed_cpp_options(cpp_options), - stanc_options_supplied = as.list(stanc_options_to_args(stanc_options)), - stanc_options_injected = as.list(stanc_options_to_args(injected)), - stanc_name = injected[["name"]], + configuration <- list( + cpp_options = parsed_cpp_options(cpp_options), + stanc_options = as.list(stanc_options_to_args(stanc_options)), + stanc_options_added = as.list(stanc_options_to_args(added)), + stanc_name = added[["name"]], include_paths = as.list(include_paths) ) @@ -77,19 +77,21 @@ build_executable <- function(stan_file, isTRUE(getOption("cmdstanr_force_recompile"))) { forced <- "force_recompile_option" } - observed <- observe_build(stan_file, include_paths, user_header, exe) + current <- read_current_build(stan_file, include_paths, user_header, exe) reasons <- c( - assess_build(list(request = request, artifact = NULL), observed), + assess_build( + list(configuration = configuration, executable_hash = NULL), current + ), forced ) rebuild <- length(reasons) > 0 if (rlang::is_interactive()) { - message(constructor_message(reasons, observed)) + message(constructor_message(reasons, current)) } # The flags stanc receives: the call's, then what make adds for this build. # On a reuse the record says what make added, since make/local is unchanged. - stancflags_call <- stanc_options_to_args(c(stanc_options, injected)) + stancflags_call <- stanc_options_to_args(c(stanc_options, added)) make_vars <- cpp_options_to_compile_flags(cpp_options) if (!is.null(user_header)) { make_vars <- c( @@ -97,17 +99,18 @@ build_executable <- function(stan_file, ) } if (rebuild) { - if (is.null(observed$info)) { - observed <- c( - observed, resolve_dependencies(stan_file, include_paths, user_header) + if (is.null(current$info)) { + current <- c( + current, resolve_dependencies(stan_file, include_paths, user_header) ) } - inherited <- inherited_stancflags(make_vars) + from_make <- stancflags_added_by_make(make_vars) } else { - inherited <- unlist(observed$record$record$request$stanc_options_inherited) + from_make <- + unlist(current$record$record$configuration$stanc_options_from_make) } - inherited <- drop_overridden_stancflags(inherited, stancflags_call) - stancflags_direct <- c(stancflags_call, inherited) + from_make <- drop_overridden_stancflags(from_make, stancflags_call) + stancflags_direct <- c(stancflags_call, from_make) stanc_inc_paths <- include_paths_stanc3_args( include_paths, direct_call = TRUE ) @@ -132,43 +135,44 @@ build_executable <- function(stan_file, ) if (!rebuild) { - record <- observed$record$record + record <- current$record$record } else { tmp_exe <- cmdstan_ext(strip_ext(source)) if (os_is_windows() && !os_is_wsl()) { tmp_exe <- utils::shortPathName(tmp_exe) } - # get_cmdstan_flags() split the inherited flags into words. Requote them + # get_cmdstan_flags() split the flags from make into words. Requote them # for the STANCFLAGS value handed back to make. stancflags_quoted <- stanc_options_to_args( - c(stanc_options, injected), quote_values = TRUE + c(stanc_options, added), quote_values = TRUE ) stancflags_make <- paste0( "STANCFLAGS += ", include_paths_stanc3_args(include_paths), paste0( - " ", c(stancflags_quoted, make_shell_quote(inherited)), collapse = "" + " ", c(stancflags_quoted, make_shell_quote(from_make)), collapse = "" ) ) run_make( c(wsl_safe_path(repair_path(tmp_exe)), make_vars, stancflags_make), quiet ) record <- new_build_record( - request = append( - request, list(stanc_options_inherited = as.list(inherited)), after = 3 + configuration = append( + configuration, list(stanc_options_from_make = as.list(from_make)), + after = 3 ), reported_features = reported_features_from_exe(tmp_exe), - dependencies = observed$dependencies, - artifact = hash_file(tmp_exe), - builder = observed$builder, + dependencies = current$dependencies, + executable_hash = hash_file(tmp_exe), + cmdstan = current$cmdstan, tbb_dir = tbb_dir_from_options(cpp_options), - known_untracked_dependencies = untracked_dependencies( - observed$dependencies$make_local$built_from, user_header + untracked_dependencies = untracked_dependencies( + current$dependencies$make_local$built_from, user_header ) ) leftover_backup <- install_executable(tmp_exe, exe, record) # Said once, when the record is written, and never on a no-op. - if (length(record$known_untracked_dependencies) > 0) { - message(untracked_dependencies_note(record$known_untracked_dependencies)) + if (length(record$untracked_dependencies) > 0) { + message(untracked_dependencies_note(record$untracked_dependencies)) } if (!is.null(leftover_backup)) { warning( @@ -182,7 +186,7 @@ build_executable <- function(stan_file, exe_file = exe, record = record, include_paths = include_paths, - info = observed$info, + info = current$info, hpp_code = hpp_code ) } @@ -192,16 +196,18 @@ build_executable <- function(stan_file, #' Three outcomes. With a usable record beside it nothing is launched: the #' hash the reader checked proves the binary is the one the record describes. #' Without one the executable is asked to identify itself with `info`, once. A -#' version it reports admits it, unprovenanced. No version refuses it, since an -#' executable that cannot say what built it is not a CmdStan executable. +#' version it reports admits it, without a record. No version refuses it, +#' since an executable that cannot say what built it is not a CmdStan +#' executable. #' -#' @return A list: `record` (`NULL` when unprovenanced), `reported_features`, -#' `version` and `artifact`, the executable's hash. +#' @return A list: `record` (`NULL` when there is no record), +#' `reported_features`, `version` and `executable_hash`, the executable's +#' hash. #' @noRd adopt_executable <- function(exe_file) { found <- read_build_record(exe_file) if (found$status == "available") { - return(snapshot_from_record(found$record)) + return(facts_from_record(found$record)) } features <- reported_features_from_exe(exe_file) if (is.null(features[["stan_version"]])) { @@ -215,50 +221,51 @@ adopt_executable <- function(exe_file) { record = NULL, reported_features = features, version = features[["stan_version"]], - artifact = hash_file(exe_file) + executable_hash = hash_file(exe_file) ) } -snapshot_from_record <- function(record) { +facts_from_record <- function(record) { list( record = record, reported_features = record$reported_features, - version = record$builder$version, - artifact = record$artifact + version = record$cmdstan$version, + executable_hash = record$executable_hash ) } #' What is on disk for an executable built from a Stan program #' -#' The `observed` argument of assess_build(): the record beside the executable, +#' The `current` argument of assess_build(): the record beside the executable, #' the installation selected now, and the sources hashed the way the writer #' hashes them, with `info`, the `stanc --info` output they were resolved -#' from, kept for the snapshot. The constructor and the guard both come here, -#' so they cannot assemble it differently. The sources are resolved through -#' the selected stanc, so they are left unresolved when the selection is not -#' the recorded builder. That difference is a reason on its own. +#' from, kept for the facts. The constructor and assert_current() both come +#' here, so they cannot assemble it differently. The sources are resolved +#' through the selected stanc, so they are left unresolved when the selection +#' is not the recorded CmdStan. That difference is a reason on its own. #' #' @noRd -observe_build <- function(stan_file, include_paths, user_header, exe_file) { - observed <- list( +read_current_build <- function(stan_file, include_paths, user_header, + exe_file) { + current <- list( exe_file = exe_file, record = list(status = "unavailable", reason = "no_executable"), - builder = list(path = cmdstan_path(), version = current_cmdstan_version()) + cmdstan = list(path = cmdstan_path(), version = current_cmdstan_version()) ) if (file.exists(exe_file)) { - observed$record <- read_build_record(exe_file) + current$record <- read_build_record(exe_file) } - same_builder <- function() { - recorded <- observed$record$record - differs <- compare_build_records(recorded, observed, "builder") + same_cmdstan <- function() { + recorded <- current$record$record + differs <- compare_build_records(recorded, current, "cmdstan") length(differs) == 0 } - if (observed$record$status == "available" && same_builder()) { - observed <- c( - observed, resolve_dependencies(stan_file, include_paths, user_header) + if (current$record$status == "available" && same_cmdstan()) { + current <- c( + current, resolve_dependencies(stan_file, include_paths, user_header) ) } - observed + current } #' Hash what a build of this program consumes @@ -295,10 +302,10 @@ resolve_dependencies <- function(stan_file, include_paths, user_header) { #' What Make resolves `STANCFLAGS` to with this build's variables applied, #' which is how make/local and CmdStan's own makefiles reach stanc. An include #' path there is refused: `include_paths` is the one channel, so that -#' re-resolution sees every path the build saw. +#' resolving again sees every path the build saw. #' #' @noRd -inherited_stancflags <- function(make_vars) { +stancflags_added_by_make <- function(make_vars) { flags <- get_cmdstan_flags("STANCFLAGS", make_vars) is_include_path <- grepl("--include-paths", flags, fixed = TRUE) | startsWith(flags, "-I") @@ -418,12 +425,12 @@ model_name_from_path <- function(path) { } -# what the constructor and the guard say ------------------------------------ +# what the constructor and assert_current() say ----------------------------- #' What the constructor says before it builds or reuses #' #' @noRd -constructor_message <- function(reasons, observed) { +constructor_message <- function(reasons, current) { if (length(reasons) == 0) { return("Model executable is up to date!") } @@ -431,7 +438,7 @@ constructor_message <- function(reasons, observed) { return("Compiling Stan program...") } paste( - c("Recompiling:", paste0(" - ", rebuild_reasons(reasons, observed))), + c("Recompiling:", paste0(" - ", rebuild_reasons(reasons, current))), collapse = "\n" ) } @@ -439,12 +446,12 @@ constructor_message <- function(reasons, observed) { #' Word the reasons assess_build() returns, one line each #' #' @noRd -rebuild_reasons <- function(reasons, observed) { - recorded <- observed$record$record - current <- observed$dependencies +rebuild_reasons <- function(reasons, current) { + recorded <- current$record$record + deps <- current$dependencies included_files <- function() { old <- recorded$dependencies$included_files - new <- current$included_files + new <- deps$included_files if (length(old) != length(new)) { return("the set of included files changed") } @@ -457,7 +464,7 @@ rebuild_reasons <- function(reasons, observed) { paste0("included files changed (", paste(paths, collapse = ", "), ")") } format_version <- function() { - written <- observed$record$format_version + written <- current$record$format_version sprintf( paste0( "the build record was written by %s version of cmdstanr (format %s; ", @@ -472,7 +479,7 @@ rebuild_reasons <- function(reasons, observed) { switch( reason, no_executable = paste0( - "there is no executable at '", observed$exe_file, "'" + "there is no executable at '", current$exe_file, "'" ), missing = paste0( "the executable has no build record, so what it was built with ", @@ -483,11 +490,11 @@ rebuild_reasons <- function(reasons, observed) { "it was built with cannot be verified" ), unsupported_format = format_version(), - artifact_mismatch = paste0( + executable_mismatch = paste0( "the executable does not match its build record, so it was replaced ", "or altered after it was built" ), - artifact = "the executable was replaced after this model was created", + executable = "the executable changed after this model was created", cpp_options = "`cpp_options` changed", stanc_options = "`stanc_options` changed", stanc_name = "the model name changed", @@ -495,21 +502,21 @@ rebuild_reasons <- function(reasons, observed) { included_files = included_files(), user_header = paste0( "the user header changed (", - (current$user_header %||% recorded$dependencies$user_header)$built_from, + (deps$user_header %||% recorded$dependencies$user_header)$built_from, ")" ), make_local = paste0( "make/local changed (", - (current$make_local %||% recorded$dependencies$make_local)$built_from, + (deps$make_local %||% recorded$dependencies$make_local)$built_from, ")" ), - builder = sprintf( + cmdstan = sprintf( paste0( "the selected CmdStan changed (built with %s at '%s'; ", "%s at '%s' is selected now)" ), - recorded$builder$version, recorded$builder$path, - observed$builder$version, observed$builder$path + recorded$cmdstan$version, recorded$cmdstan$path, + current$cmdstan$version, current$cmdstan$path ), force_recompile = "`force_recompile = TRUE` was supplied", force_recompile_option = "the `cmdstanr_force_recompile` option is set" @@ -518,7 +525,7 @@ rebuild_reasons <- function(reasons, observed) { vapply(reasons, line, character(1), USE.NAMES = FALSE) } -#' The error a guarded member raises on a stale executable +#' The error a checked method raises on a stale executable #' #' Carries the class `cmdstanr_stale_executable` so callers can catch it by #' what it means rather than by its text. diff --git a/R/build_record.R b/R/build_record.R index 62fb6737b..5c6dfb045 100644 --- a/R/build_record.R +++ b/R/build_record.R @@ -120,34 +120,38 @@ validate_build_record <- function(record) { ) } - request <- record_member(record, "request", "object") + configuration <- record_member(record, "configuration", "object") cpp_options <- record_member( - request, "cpp_options_supplied", "object", "request.cpp_options_supplied" + configuration, "cpp_options", "object", "configuration.cpp_options" ) for (i in seq_along(cpp_options)) { option_name <- names(cpp_options)[[i]] - field <- paste0("request.cpp_options_supplied.", option_name) + field <- paste0("configuration.cpp_options.", option_name) if (!grepl(paste0("^", make_variable_name_pattern, "$"), option_name)) { stop_build_record_field(field, "must be named for a Make variable") } record_shape(cpp_options[[i]], "string", field) } record_string_array( - request, "stanc_options_supplied", "request.stanc_options_supplied" + configuration, "stanc_options", "configuration.stanc_options" ) record_string_array( - request, "stanc_options_injected", "request.stanc_options_injected" + configuration, "stanc_options_added", + "configuration.stanc_options_added" ) record_string_array( - request, "stanc_options_inherited", "request.stanc_options_inherited" + configuration, "stanc_options_from_make", + "configuration.stanc_options_from_make" ) stanc_name <- record_member( - request, "stanc_name", "string", "request.stanc_name" + configuration, "stanc_name", "string", "configuration.stanc_name" ) if (!nzchar(stanc_name)) { - stop_build_record_field("request.stanc_name", "must not be empty") + stop_build_record_field("configuration.stanc_name", "must not be empty") } - record_string_array(request, "include_paths", "request.include_paths") + record_string_array( + configuration, "include_paths", "configuration.include_paths" + ) reported_features <- record_member(record, "reported_features", "object") for (i in seq_along(reported_features)) { @@ -173,23 +177,23 @@ validate_build_record <- function(record) { ) } - record_member(record, "artifact", "string") + record_member(record, "executable_hash", "string") - builder <- record_member(record, "builder", "object") - record_member(builder, "path", "string", "builder.path") - version <- record_member(builder, "version", "string", "builder.version") + cmdstan <- record_member(record, "cmdstan", "object") + record_member(cmdstan, "path", "string", "cmdstan.path") + version <- record_member(cmdstan, "version", "string", "cmdstan.version") # A string that is not a CmdStan version is the wrong shape, not an odd value. if (!grepl(cmdstan_version_pattern, version)) { stop_build_record_field( - "builder.version", "must be a CmdStan version such as \"2.39.0\"" + "cmdstan.version", "must be a CmdStan version such as \"2.39.0\"" ) } record_member(record, "tbb_dir", "string") - untracked <- record_member(record, "known_untracked_dependencies", "array") + untracked <- record_member(record, "untracked_dependencies", "array") for (i in seq_along(untracked)) { - field <- paste0("known_untracked_dependencies[[", i, "]]") + field <- paste0("untracked_dependencies[[", i, "]]") entry <- record_shape(untracked[[i]], "object", field) kind <- record_member(entry, "kind", "string", paste0(field, ".kind")) if (!kind %in% c("make_local_include", "user_header_include")) { @@ -210,23 +214,23 @@ validate_build_record <- function(record) { #' #' The one place a record is built. `format_version` comes first and the rest #' follow the schema's order, so the written JSON reads in that order too. -#' `request` arrives in the forms the record compares: `cpp_options_supplied` -#' as canonical Make assignments, one per name, and the three stanc option +#' `configuration` arrives in the forms the record compares: `cpp_options` +#' as normalized Make assignments, one per name, and the three stanc option #' lists as the argument vectors stanc receives. #' #' @noRd -new_build_record <- function(request, reported_features, dependencies, artifact, - builder, tbb_dir, - known_untracked_dependencies = list()) { +new_build_record <- function(configuration, reported_features, dependencies, + executable_hash, cmdstan, tbb_dir, + untracked_dependencies = list()) { record <- list( format_version = build_record_format_version, - request = request, + configuration = configuration, reported_features = reported_features, dependencies = dependencies, - artifact = artifact, - builder = builder, + executable_hash = executable_hash, + cmdstan = cmdstan, tbb_dir = tbb_dir, - known_untracked_dependencies = known_untracked_dependencies + untracked_dependencies = untracked_dependencies ) validate_build_record(record) record @@ -410,8 +414,8 @@ read_build_record <- function(exe_file) { if (!accepted) { return(unreadable) } - if (!identical(hash_file(exe_file), record[["artifact"]])) { - return(list(status = "unavailable", reason = "artifact_mismatch")) + if (!identical(hash_file(exe_file), record[["executable_hash"]])) { + return(list(status = "unavailable", reason = "executable_mismatch")) } list(status = "available", record = record) @@ -444,11 +448,11 @@ verify_build_record <- function(exe_file) { #' @noRd build_record_comparisons <- list( cpp_options = function(x) { - supplied <- x[["request"]][["cpp_options_supplied"]] + supplied <- x[["configuration"]][["cpp_options"]] supplied[order(names(supplied))] }, - stanc_options = function(x) x[["request"]][["stanc_options_supplied"]], - stanc_name = function(x) x[["request"]][["stanc_name"]], + stanc_options = function(x) x[["configuration"]][["stanc_options"]], + stanc_name = function(x) x[["configuration"]][["stanc_name"]], stan_file = function(x) x[["dependencies"]][["stan_file"]][["hash"]], included_files = function(x) { lapply(x[["dependencies"]][["included_files"]], `[[`, "hash") @@ -457,8 +461,8 @@ build_record_comparisons <- list( x[["dependencies"]][["user_header"]][c("hash", "built_from")] }, make_local = function(x) x[["dependencies"]][["make_local"]]["hash"], - artifact = function(x) x[["artifact"]], - builder = function(x) x[["builder"]][c("path", "version")] + executable = function(x) x[["executable_hash"]], + cmdstan = function(x) x[["cmdstan"]][c("path", "version")] ) #' Compare a recorded build against the current one @@ -481,42 +485,42 @@ compare_build_records <- function(recorded, current, #' Decide whether an executable is current #' -#' Takes two lists and compares them. `expected` is what the caller wants -#' the executable to have been built from. Its `request` holds the options -#' this call would record. Its `artifact` is the hash the object was built -#' against, or `NULL` at the constructor, which has no expectation yet. -#' `observed` is what is there now. Its `record` is what +#' Takes two lists and compares them. `wanted` is what the caller wants +#' the executable to have been built from. Its `configuration` holds the +#' options this call would record. Its `executable_hash` is the hash the +#' object was built against, or `NULL` at the constructor, which has no +#' expectation yet. `current` is what is there now. Its `record` is what #' `read_build_record()` returned. Its `dependencies` are the current files #' hashed the way the writer hashes them, or `NULL` when nobody resolved -#' them. Its `builder` is the installation selected now. +#' them. Its `cmdstan` is the installation selected now. #' #' Returns a character vector of reasons to rebuild, empty when the #' executable is current. When the record cannot be used the vector holds #' that one reason and nothing else, because there is no baseline to compare #' the rest against. Otherwise it names every compared row that differs. #' The dependency rows are skipped when nobody resolved them, so an -#' unresolved set is never mistaken for an empty one. The expected artifact +#' unresolved set is never mistaken for an empty one. The wanted executable #' hash is what catches an executable another process rebuilt, since the #' record beside it then matches it and nothing on disk disagrees. Reads no #' file and runs nothing. #' #' @noRd -assess_build <- function(expected, observed) { - if (observed$record$status != "available") { - return(observed$record$reason) +assess_build <- function(wanted, current) { + if (current$record$status != "available") { + return(current$record$reason) } - recorded <- observed$record$record - current <- list( - request = expected$request, - dependencies = observed$dependencies, - artifact = expected$artifact %||% recorded$artifact, - builder = observed$builder + recorded <- current$record$record + now <- list( + configuration = wanted$configuration, + dependencies = current$dependencies, + executable_hash = wanted$executable_hash %||% recorded$executable_hash, + cmdstan = current$cmdstan ) rows <- names(build_record_comparisons) - if (is.null(observed$dependencies)) { + if (is.null(current$dependencies)) { rows <- setdiff( rows, c("stan_file", "included_files", "user_header", "make_local") ) } - compare_build_records(recorded, current, rows) + compare_build_records(recorded, now, rows) } diff --git a/R/model.R b/R/model.R index c6cc8694f..f713e465e 100644 --- a/R/model.R +++ b/R/model.R @@ -347,7 +347,7 @@ CmdStanModel <- R6::R6Class( include_paths_ = NULL, user_header_ = NULL, exe_file_ = character(), - artifact_ = NULL, + executable_hash_ = NULL, record_ = NULL, reported_features_ = NULL, cmdstan_version_ = NULL, @@ -366,46 +366,51 @@ CmdStanModel <- R6::R6Class( paste0("The executable at '", exe, "' no longer exists.") ) } - if (!identical(hash_file(exe), private$artifact_)) { + if (!identical(hash_file(exe), private$executable_hash_)) { stop_stale_executable(paste0( "The executable at '", exe, - "' was replaced after this model was created." + "' changed after this model was created." )) } return(invisible(self)) } assert_stan_file_exists(private$stan_file_) - observed <- observe_build( + current <- read_current_build( private$stan_file_, private$include_paths_, private$user_header_, exe ) reasons <- assess_build( - list(request = private$record_$request, artifact = private$artifact_), - observed + list( + configuration = private$record_$configuration, + executable_hash = private$executable_hash_ + ), + current ) if (length(reasons) > 0) { stop_stale_executable(c( "The executable is out of date:", - paste0(" - ", rebuild_reasons(reasons, observed)), + paste0(" - ", rebuild_reasons(reasons, current)), "Run cmdstan_model() to rebuild it." )) } invisible(self) }, - # The standalone-functions C++, generated from the source once, on the - # first call that has passed the guard, when the source is known to be - # the built one. Construction does not pay a stanc run for a feature most - # models never use. Fits copy it from here. Empty without a source. + # The standalone-functions C++, generated from the source once, after + # assert_current() has passed, when the source is known to be the built + # one. Construction does not pay a stanc run for a feature most models + # never use. Fits copy it from here. Empty without a source. standalone_functions = function() { if (self$has_stan_file() && is.null(self$functions$hpp_code)) { - request <- private$record_$request + configuration <- private$record_$configuration self$functions$hpp_code <- get_standalone_hpp( private$stan_file_, c("--standalone-functions", include_paths_stanc3_args( private$include_paths_, direct_call = TRUE ), - unlist(request[c("stanc_options_supplied", "stanc_options_injected", - "stanc_options_inherited")], use.names = FALSE)) + unlist(configuration[c( + "stanc_options", "stanc_options_added", + "stanc_options_from_make" + )], use.names = FALSE)) ) } self$functions @@ -448,7 +453,7 @@ CmdStanModel <- R6::R6Class( writeLines(built$hpp_code, private$hpp_file_) private$model_methods_env_ <- new.env() private$model_methods_env_$hpp_code_ <- built$hpp_code - snapshot <- snapshot_from_record(built$record) + facts <- facts_from_record(built$record) } else { assert_no_build_args_for_exe_only( cpp_options, stanc_options, include_paths, user_header, @@ -458,14 +463,14 @@ CmdStanModel <- R6::R6Class( assert_file_exists(exe_file, access = "r", extension = ext) private$exe_file_ <- resolve_path(exe_file) private$model_name_ <- model_name_from_path(private$exe_file_) - snapshot <- adopt_executable(private$exe_file_) + facts <- adopt_executable(private$exe_file_) } - private$record_ <- snapshot$record - private$artifact_ <- snapshot$artifact - private$reported_features_ <- snapshot$reported_features - private$cmdstan_version_ <- snapshot$version + private$record_ <- facts$record + private$executable_hash_ <- facts$executable_hash + private$reported_features_ <- facts$reported_features + private$cmdstan_version_ <- facts$version private$user_header_ <- - snapshot$record$dependencies[["user_header"]][["built_from"]] + facts$record$dependencies[["user_header"]][["built_from"]] invisible(self) }, include_paths = function() { @@ -511,7 +516,7 @@ CmdStanModel <- R6::R6Class( private$cmdstan_version_ }, cpp_options = function() { - private$record_$request$cpp_options_supplied %||% + private$record_$configuration$cpp_options %||% structure(list(), names = character()) }, user_header = function() { diff --git a/dev-notes/compilation-state-contract.md b/dev-notes/compilation-state-contract.md index 122969a37..ad52fbb02 100644 --- a/dev-notes/compilation-state-contract.md +++ b/dev-notes/compilation-state-contract.md @@ -10,12 +10,12 @@ it. ## [1. Vocabulary: what the record is, and what it is not](compilation-state.md#1-vocabulary-what-the-record-is-and-what-it-is-not) -The record describes how an executable came to exist. It is not a configuration -store, it does not authorise whatever happens to be at the executable path, and it -does not replace looking at the binary itself. Its fields are different kinds of -fact: +The record describes how an executable came to exist. It cannot be fed back into +a build, it does not authorise whatever happens to be at the executable path, and +it does not replace looking at the binary itself. Its fields are different kinds +of fact: -- **`request`**: the build configuration. `stanc_options` is stored two ways, what +- **`configuration`**: what the build was asked for. `stanc_options` is stored two ways, what the caller supplied and what cmdstanr injected. The two are disjoint because cmdstanr injects only what the caller did not supply. Which list a value lands in is decided by where it came from; whether it can force a rebuild is decided per @@ -26,16 +26,16 @@ fact: explain a build. Feeding them back into another build is not supported and no rule here depends on it. - **`reported_features`**: what the binary reports as enabled. Kept apart from - `request` because `make/local` can enable threading or OpenCL the user never - mentioned. `request` is everything settled before the build ran; `reported_features` + `configuration` because `make/local` can enable threading or OpenCL the user never + mentioned. `configuration` is everything settled before the build ran; `reported_features` is what could only be discovered afterward. - **`dependencies`**: the sources consumed, and enough about how they were resolved to resolve them again. Identified by content; each also records the `built_from` path it had at build time (§4). -- **`artifact`**: a hash of the executable this record describes, used only to check - that a record and an executable belong together (§4). -- **`builder`**: the CmdStan installation that produced it. -- **`known_untracked_dependencies`**: dependencies we can see exist but cannot +- **`executable_hash`**: a hash of the executable this record describes, used only to + check that a record and an executable belong together (§4). +- **`cmdstan`**: the CmdStan installation that produced it. +- **`untracked_dependencies`**: dependencies we can see exist but cannot resolve (§6). An empty list means nothing was detected, never that the record is complete. - **`format_version`**: which format the record is written in. 1.0 reads only the @@ -51,7 +51,7 @@ never be read as disabled.** only when the state is known, and let an absent key mean unknown. **Request and reported features are never merged into one accessor.** -`$cpp_options()` reports `cpp_options_supplied`, what the caller asked for and not +`$cpp_options()` reports `cpp_options`, what the caller asked for and not what cmdstanr added. The user header has its own accessor, `$user_header()`, matching its own argument; it is not readable through `$cpp_options()` because it is no longer settable there (§3). `stan_build_info()` reports what the binary says, with its @@ -235,33 +235,33 @@ contains.** | Field | Recorded | Compared | Notes | |---|---|---|---| -| `request.cpp_options_supplied` | yes | yes | what the caller passed; canonicalized per field (§3, #1250) | -| `request.stanc_options_supplied` | yes | yes | as above | -| `request.stanc_options_injected` | yes | **no** | what cmdstanr added, disjoint from `_supplied` by construction. Never compared as a list; whether an injection's effect is compared is decided per field like every other row, and the model name is the one that earns its own, below | -| `request.stanc_options_inherited` | yes | **no** | the `STANCFLAGS` make added for the build, as passed to make after the call's own flags displaced their make/local copies (§6). A reuse regenerates the model's C++ (§5) with them, instead of asking make again on every construction. Not compared: `make/local` is, and what an included makefile or the environment adds is untracked (§6) | -| `request.stanc_name` | yes | **yes** | the `--name` stanc receives, which `R/model.R:835` derives from the file name; §3 rejects the `stanc_options` spelling, so this is the only source. The build bakes it into the binary, and no other compared field pins it down, since content hashes are compared and paths are not. Its visible effect is the CSV header (`R/csv.R:873`), which carries both the raw value stanc was passed and the mangled one stanc compiled | -| `request.include_paths`, effective | yes | **no** | the paths in force for the call drive re-resolution (§6): this call's at the constructor, the object's own at a guarded method, never the recorded ones (§5). The recorded value is provenance | +| `configuration.cpp_options` | yes | yes | what the caller passed; canonicalized per field (§3, #1250) | +| `configuration.stanc_options` | yes | yes | as above | +| `configuration.stanc_options_added` | yes | **no** | what cmdstanr added, disjoint from `stanc_options` by construction. Never compared as a list; whether an injection's effect is compared is decided per field like every other row, and the model name is the one that earns its own, below | +| `configuration.stanc_options_from_make` | yes | **no** | the `STANCFLAGS` make added for the build, as passed to make after the call's own flags displaced their make/local copies (§6). A reuse regenerates the model's C++ (§5) with them, instead of asking make again on every construction. Not compared: `make/local` is, and what an included makefile or the environment adds is untracked (§6) | +| `configuration.stanc_name` | yes | **yes** | the `--name` stanc receives, which `R/model.R:835` derives from the file name; §3 rejects the `stanc_options` spelling, so this is the only source. The build bakes it into the binary, and no other compared field pins it down, since content hashes are compared and paths are not. Its visible effect is the CSV header (`R/csv.R:873`), which carries both the raw value stanc was passed and the mangled one stanc compiled | +| `configuration.include_paths`, effective | yes | **no** | the paths in force for the call drive re-resolution (§6): this call's at the constructor, the object's own at a guarded method, never the recorded ones (§5). The recorded value is provenance | | `reported_features` | yes | no | describes the binary; never a trigger (§1) | | `dependencies[].hash` | yes | yes | content hash; this is what identity means | | `dependencies[].built_from` | yes | no | where the file was at build time; provenance. The user header is the exception below | | `dependencies.user_header.built_from` | yes | **yes** | the one *dependency* path compared, because the C++ closure beneath it cannot be enumerated. `-I` flags decide the same resolution and are compared inside `cpp_options` above (§6) | | `dependencies.included_files` | yes | yes | **ordered sequence**, duplicates preserved (§6) | -| `artifact` | yes | yes | hash of the executable this record describes | -| `builder` | yes | yes | normalized installation path and version | -| `tbb_dir` | yes | **no** | the absolute TBB directory the call named, read as `make` receives the call's `cpp_options` (§3: last assignment wins, `FALSE` is an empty one): `TBB_LIB`, or `TBB_BIN` when `TBB_LIB` is empty, which is the order `compiler_flags` uses; resolved against the installation when relative, since `make` runs there; and the installation's own `lib/tbb` when the call named neither. Filled from the call, not asked of `make`: a `TBB_LIB` or `TBB_BIN` set in `make/local`, `~/.config/stan/make.local` or the environment moves the TBB the binary links against and not this field (§6). Recorded because Windows needs it at launch and a later `set_cmdstan_path()` must not move it (#1261 consumes it; no verdict here turns on it). Not compared: both routes it sees are compared already, through `cpp_options_supplied` and `builder` | -| `known_untracked_dependencies` | yes | no | reported (§6), never a trigger | +| `executable_hash` | yes | yes | hash of the executable this record describes | +| `cmdstan` | yes | yes | normalized installation path and version | +| `tbb_dir` | yes | **no** | the absolute TBB directory the call named, read as `make` receives the call's `cpp_options` (§3: last assignment wins, `FALSE` is an empty one): `TBB_LIB`, or `TBB_BIN` when `TBB_LIB` is empty, which is the order `compiler_flags` uses; resolved against the installation when relative, since `make` runs there; and the installation's own `lib/tbb` when the call named neither. Filled from the call, not asked of `make`: a `TBB_LIB` or `TBB_BIN` set in `make/local`, `~/.config/stan/make.local` or the environment moves the TBB the binary links against and not this field (§6). Recorded because Windows needs it at launch and a later `set_cmdstan_path()` must not move it (#1261 consumes it; no verdict here turns on it). Not compared: both routes it sees are compared already, through `cpp_options` and `cmdstan` | +| `untracked_dependencies` | yes | no | reported (§6), never a trigger | | `format_version` | yes | **no** | not a comparison: the reader either reads the record's version or does not, which is an artifact-side reason like unreadable JSON (§6) | **Origin is stored, not inferred.** **A change to which options cmdstanr injects does not rebuild anything already built.** An option a later cmdstanr adds can change the artifact while an old -record's `_supplied` goes on matching, and nothing rebuilds. That is the intended +record's `stanc_options` goes on matching, and nothing rebuilds. That is the intended answer: the caller asked for the same build they asked for before, and the new binary is theirs to ask for with `force_recompile = TRUE`. CmdStan is not an exception to that rule. A CmdStan upgrade does rebuild, through -`builder`, because the installation is a standing runtime dependency of the artifact +`cmdstan`, because the installation is a standing runtime dependency of the artifact rather than a fact about how it was built: the binary loads its TBB through an absolute rpath, by default into that tree (§6), and re-resolution invokes that installation's stanc (§6). @@ -318,7 +318,7 @@ of one destination is unsupported; locking is tracked separately. **What the reader cannot use, it rejects as unreadable rather than working with.** A file that parses as JSON is not yet a record (§6). Every field the format requires -is checked for type and shape before the record is accepted, `builder`'s version +is checked for type and shape before the record is accepted, `cmdstan`'s version against the grammar §7 defines since a string that is not a CmdStan version is the wrong shape rather than an odd value, and a record failing any of those checks is unreadable whole: nothing in it is used and nothing in it is reported, including a @@ -507,7 +507,7 @@ marks **compared** differs from what this call computes. Which fields those are Or when the record cannot be used at all: -- the executable does not match `artifact`: replaced by another process, or corrupt +- the executable does not match `executable_hash`: replaced by another process, or corrupt - the record is missing, unreadable, or written in a format version this cmdstanr does not read - the executable predates build records, so there is nothing to compare @@ -630,7 +630,7 @@ models the regex detects. The comparison is the normalised installation path and the version, plus the `make/local` hash, which is its own dependency with its own trigger rather than -part of `builder`. +part of `cmdstan`. **A different path at the same version is a rebuild reason.** @@ -664,7 +664,7 @@ different executable would supply the wrong baseline. they were, so that an unresolved set is never read as an empty one. One path reaches it: re-resolution is skipped when the selected -installation differs from `builder` (below). That difference is itself a trigger, +installation differs from `cmdstan` (below). That difference is itself a trigger, so the verdict is the same either way and only the reason list is shorter. `make/local` is per-installation, so editing it invalidates every model built @@ -682,10 +682,10 @@ provenance (§4). **Re-resolve by invoking stanc, never by reimplementing its rules.** -**Invoke stanc from the recorded `builder`, not from whichever installation is +**Invoke stanc from the recorded `cmdstan`, not from whichever installation is selected now**, or a different stanc's resolution rules get applied to a model this one did not build. **Check builder identity first**: if the selected installation -differs from `builder`, that is already a rebuild trigger (above) and should be +differs from `cmdstan`, that is already a rebuild trigger (above) and should be reported without attempting re-resolution at all. **Normalisation: normalised absolute paths, recorded but not compared.** @@ -712,7 +712,7 @@ In both cases a regex, `^\s*(?:-?include|sinclude)\b` for `make/local` and `^\s*#\s*include\s*"` for the user header, tells us there is an untracked dependency, without resolving anything. -**The field is `known_untracked_dependencies`, not `provenance_complete`.** +**The field is `untracked_dependencies`, not `provenance_complete`.** **No match means "no known gap", never "complete".** @@ -778,7 +778,7 @@ freshness may still be unverifiable. If the recorded sources are absent or the paths no longer resolve, say so specifically rather than collapsing it to unknown provenance. -`$cpp_options()` returns the recorded `cpp_options_supplied` here, and +`$cpp_options()` returns the recorded `cpp_options` here, and `$user_header()` the recorded header path. **Adoption establishes what the artifact is, not that it runs.** A hash-matched @@ -787,7 +787,7 @@ this machine adopts successfully and fails when something first runs it, with th launch error §6 requires. **Executable without a usable record**: missing, unreadable (an unparseable -`builder` version among the field checks that decide it, §4), hash mismatch, or +`cmdstan` version among the field checks that decide it, §4), hash mismatch, or written in a format version this cmdstanr does not read. Explicitly unprovenanced, which is a statement about provenance and must not suppress what the binary does report. `stan_build_info()` returns an explicit unavailable provenance, never an @@ -954,13 +954,13 @@ are the promise, and the record's layout is free underneath them. | field | present when | holds | |---|---|---| -| `provenance` | always | `status` and `reason`, both always present | +| `record` | always | `status` and `reason`, both always present | | `reported_features` | always | one entry per feature: four logical flags, each `TRUE`, `FALSE` or `NA`, and `stan_version`, a character scalar or `NA_character_` | | `format_version` | `unsupported_format` only (below) | the format the record was written in | -| `request` | provenance available | the recorded build configuration of §1 | -| `dependencies` | provenance available | every file whose content the build consumed | -| `builder` | provenance available | installation path, version, `exists` | -| `known_untracked_dependencies` | provenance available | §6's list; empty means nothing was detected | +| `configuration` | record available | the recorded build configuration of §1 | +| `dependencies` | record available | every file whose content the build consumed | +| `cmdstan` | record available | installation path, version, `exists` | +| `untracked_dependencies` | record available | §6's list; empty means nothing was detected | **A field is public only if a caller can act on it.** @@ -971,15 +971,15 @@ that includes another makefile: ```r list( - provenance = list(status = "available", reason = NULL), + record = list(status = "available", reason = NULL), reported_features = list( stan_threads = TRUE, stan_mpi = FALSE, stan_opencl = FALSE, stan_no_range_checks = FALSE, stan_version = "2.39.0" ), - request = list( - cpp_options_supplied = list(STAN_THREADS = TRUE), - stanc_options_supplied = list(), - include_paths = "/proj" + configuration = list( + cpp_options = list(STAN_THREADS = TRUE), + stanc_options = list(), + include_paths = "/proj" ), dependencies = list( stan_file = list(built_from = "/proj/bernoulli.stan", exists = TRUE), @@ -989,8 +989,8 @@ list( user_header = NULL, make_local = list(built_from = "/cmdstan-2.39.0/make/local", exists = TRUE) ), - builder = list(path = "/cmdstan-2.39.0", version = "2.39.0", exists = TRUE), - known_untracked_dependencies = list( + cmdstan = list(path = "/cmdstan-2.39.0", version = "2.39.0", exists = TRUE), + untracked_dependencies = list( list(kind = "make_local_include", detected_in = "/cmdstan-2.39.0/make/local") ) ) @@ -1018,18 +1018,18 @@ are the four booleans ` info` prints, `stan_threads`, `stan_mpi`, `stan_opencl` and `stan_no_range_checks`, plus `stan_version`, and the table above has their types. They are always all present. -**`provenance` carries why, not only whether.** +**`record` carries why, not only whether.** ```r -provenance = list(status = "available", reason = NULL) -provenance = list(status = "unavailable", reason = "record_missing") - # "record_unreadable" - # "artifact_mismatch" - # "unsupported_format" +record = list(status = "available", reason = NULL) +record = list(status = "unavailable", reason = "missing") + # "unreadable" + # "executable_mismatch" + # "unsupported_format" ``` Both names are always there. `available` requires `reason = NULL`, `unavailable` -requires exactly one code, and `names(provenance)` is the same pair either way, +requires exactly one code, and `names(record)` is the same pair either way, which is what a test can hold. The enum is machine-readable and no free-form message is stored. @@ -1045,15 +1045,15 @@ for an older one. **Unknown and empty must never render alike, anywhere in the result.** An empty -`known_untracked_dependencies` means the scan detected nothing; no record to scan +`untracked_dependencies` means the scan detected nothing; no record to scan means the field is absent. A recorded builder whose path is gone is -`exists = FALSE`; an absent `builder` means there was no usable record to read one +`exists = FALSE`; an absent `cmdstan` means there was no usable record to read one from, which is the only way it can be missing. An unknown request is absent, not `list()`. **A readable record whose hash does not match is read only to say why.** -`artifact_mismatch` returns no record-derived field at all, even though `request`, -`dependencies` and `builder` all parsed. `reported_features` still comes back, read +`executable_mismatch` returns no record-derived field at all, even though `configuration`, +`dependencies` and `cmdstan` all parsed. `reported_features` still comes back, read off the executable rather than the record, which is the general rule below and not an exception to this one. diff --git a/dev-notes/compilation-state.md b/dev-notes/compilation-state.md index ac47bd963..fe6cd552b 100644 --- a/dev-notes/compilation-state.md +++ b/dev-notes/compilation-state.md @@ -32,7 +32,7 @@ known about an executable cmdstanr did not build. **Out of scope:** the toolchain itself, meaning the compiler version and system libraries, which are untracked (§6). The CmdStan installation is in scope: its -normalised path and version together are the `builder` identity, and §6 also checks +normalised path and version together are the `cmdstan` identity, and §6 also checks that the installation still exists. --- @@ -75,12 +75,12 @@ that build are `cmdstan_model()` and `compile_stan_file()` (§8). -The record describes how an executable came to exist. It is not a configuration -store, it does not authorise whatever happens to be at the executable path, and it -does not replace looking at the binary itself. Its fields are different kinds of -fact: +The record describes how an executable came to exist. It cannot be fed back into +a build, it does not authorise whatever happens to be at the executable path, and +it does not replace looking at the binary itself. Its fields are different kinds +of fact: -- **`request`**: the build configuration. `stanc_options` is stored two ways, what +- **`configuration`**: what the build was asked for. `stanc_options` is stored two ways, what the caller supplied and what cmdstanr injected. The two are disjoint because cmdstanr injects only what the caller did not supply. Which list a value lands in is decided by where it came from; whether it can force a rebuild is decided per @@ -91,16 +91,16 @@ fact: explain a build. Feeding them back into another build is not supported and no rule here depends on it. - **`reported_features`**: what the binary reports as enabled. Kept apart from - `request` because `make/local` can enable threading or OpenCL the user never - mentioned. `request` is everything settled before the build ran; `reported_features` + `configuration` because `make/local` can enable threading or OpenCL the user never + mentioned. `configuration` is everything settled before the build ran; `reported_features` is what could only be discovered afterward. - **`dependencies`**: the sources consumed, and enough about how they were resolved to resolve them again. Identified by content; each also records the `built_from` path it had at build time (§4). -- **`artifact`**: a hash of the executable this record describes, used only to check - that a record and an executable belong together (§4). -- **`builder`**: the CmdStan installation that produced it. -- **`known_untracked_dependencies`**: dependencies we can see exist but cannot +- **`executable_hash`**: a hash of the executable this record describes, used only to + check that a record and an executable belong together (§4). +- **`cmdstan`**: the CmdStan installation that produced it. +- **`untracked_dependencies`**: dependencies we can see exist but cannot resolve (§6). An empty list means nothing was detected, never that the record is complete. - **`format_version`**: which format the record is written in. 1.0 reads only the @@ -137,7 +137,7 @@ schema; this is the constraint it satisfies. **Request and reported features are never merged into one accessor.** -`$cpp_options()` reports `cpp_options_supplied`, what the caller asked for and not +`$cpp_options()` reports `cpp_options`, what the caller asked for and not what cmdstanr added. The user header has its own accessor, `$user_header()`, matching its own argument; it is not readable through `$cpp_options()` because it is no longer settable there (§3). `stan_build_info()` reports what the binary says, with its @@ -484,7 +484,7 @@ there is no other argument to redirect to. **`$user_header()` is added**, so the dedicated argument has a dedicated accessor. Today the only way to read the header back is `$cpp_options()[["USER_HEADER"]]`. -That is why §1 can have `$cpp_options()` report `cpp_options_supplied` without +That is why §1 can have `$cpp_options()` report `cpp_options` without losing anything: the header was never really a `cpp_option`, and now it is not one at all. @@ -493,12 +493,12 @@ writes the header back into `cpp_options` under whichever spelling was used, and `:941` then stores that list, so a caller who passed `user_header = "inc/mine.hpp"` as an argument and never touched `cpp_options` gets `USER_HEADER = "/abs/path/inc/mine.hpp"` back from `$cpp_options()`. Wired to -`cpp_options_supplied` with that line still in place, the accessor would report a +`cpp_options` with that line still in place, the accessor would report a field the caller never passed, holding a path they never wrote. What survives is only the Make flag: CmdStan reads `-include $(USER_HEADER)` (`make/program:41`), so `USER_HEADER=` still has to reach `make`. **It reaches it as a flag built with the others, not as a recorded `cpp_options` entry.** A recorded option would put the -header's path in `request` as well as in `dependencies` (§8), and under WSL not +header's path in `configuration` as well as in `dependencies` (§8), and under WSL not even in the same spelling, since the Make side is `wsl_safe_path()`-transformed (`R/utils.R:627`) and `built_from` is not. `resolved_header$spelling` goes with the line, since `R/model.R:709` is its only consumer and one channel has one @@ -564,7 +564,7 @@ a source-backed model whose executable already exists. Today that is the only ch there is: `cmdstan_model(f, cpp_options = list(stan_threads = TRUE))` against an unthreaded executable warns from it, and twelve assertions in three test files expect the warning. From Stage 4 the engine compares the request against the record's -`cpp_options_supplied` and rebuilds on a difference (§6), so a request-against-report +`cpp_options` and rebuilds on a difference (§6), so a request-against-report diff has no job left, and with only an executable §7 makes the request an error. The helper goes in the pull request that wires the engine (#1255), with its branch and its tests, which turn from expecting the warning into expecting the rebuild. @@ -865,21 +865,21 @@ must not restate it. A rule written in two places is a future inconsistency. | Field | Recorded | Compared | Notes | |---|---|---|---| -| `request.cpp_options_supplied` | yes | yes | what the caller passed; canonicalized per field (§3, #1250) | -| `request.stanc_options_supplied` | yes | yes | as above | -| `request.stanc_options_injected` | yes | **no** | what cmdstanr added, disjoint from `_supplied` by construction. Never compared as a list; whether an injection's effect is compared is decided per field like every other row, and the model name is the one that earns its own, below | -| `request.stanc_options_inherited` | yes | **no** | the `STANCFLAGS` make added for the build, as passed to make after the call's own flags displaced their make/local copies (§6). A reuse regenerates the model's C++ (§5) with them, instead of asking make again on every construction. Not compared: `make/local` is, and what an included makefile or the environment adds is untracked (§6) | -| `request.stanc_name` | yes | **yes** | the `--name` stanc receives, which `R/model.R:835` derives from the file name; §3 rejects the `stanc_options` spelling, so this is the only source. The build bakes it into the binary, and no other compared field pins it down, since content hashes are compared and paths are not. Its visible effect is the CSV header (`R/csv.R:873`), which carries both the raw value stanc was passed and the mangled one stanc compiled | -| `request.include_paths`, effective | yes | **no** | the paths in force for the call drive re-resolution (§6): this call's at the constructor, the object's own at a guarded method, never the recorded ones (§5). The recorded value is provenance | +| `configuration.cpp_options` | yes | yes | what the caller passed; canonicalized per field (§3, #1250) | +| `configuration.stanc_options` | yes | yes | as above | +| `configuration.stanc_options_added` | yes | **no** | what cmdstanr added, disjoint from `stanc_options` by construction. Never compared as a list; whether an injection's effect is compared is decided per field like every other row, and the model name is the one that earns its own, below | +| `configuration.stanc_options_from_make` | yes | **no** | the `STANCFLAGS` make added for the build, as passed to make after the call's own flags displaced their make/local copies (§6). A reuse regenerates the model's C++ (§5) with them, instead of asking make again on every construction. Not compared: `make/local` is, and what an included makefile or the environment adds is untracked (§6) | +| `configuration.stanc_name` | yes | **yes** | the `--name` stanc receives, which `R/model.R:835` derives from the file name; §3 rejects the `stanc_options` spelling, so this is the only source. The build bakes it into the binary, and no other compared field pins it down, since content hashes are compared and paths are not. Its visible effect is the CSV header (`R/csv.R:873`), which carries both the raw value stanc was passed and the mangled one stanc compiled | +| `configuration.include_paths`, effective | yes | **no** | the paths in force for the call drive re-resolution (§6): this call's at the constructor, the object's own at a guarded method, never the recorded ones (§5). The recorded value is provenance | | `reported_features` | yes | no | describes the binary; never a trigger (§1) | | `dependencies[].hash` | yes | yes | content hash; this is what identity means | | `dependencies[].built_from` | yes | no | where the file was at build time; provenance. The user header is the exception below | | `dependencies.user_header.built_from` | yes | **yes** | the one *dependency* path compared, because the C++ closure beneath it cannot be enumerated. `-I` flags decide the same resolution and are compared inside `cpp_options` above (§6) | | `dependencies.included_files` | yes | yes | **ordered sequence**, duplicates preserved (§6) | -| `artifact` | yes | yes | hash of the executable this record describes | -| `builder` | yes | yes | normalized installation path and version | -| `tbb_dir` | yes | **no** | the absolute TBB directory the call named, read as `make` receives the call's `cpp_options` (§3: last assignment wins, `FALSE` is an empty one): `TBB_LIB`, or `TBB_BIN` when `TBB_LIB` is empty, which is the order `compiler_flags` uses; resolved against the installation when relative, since `make` runs there; and the installation's own `lib/tbb` when the call named neither. Filled from the call, not asked of `make`: a `TBB_LIB` or `TBB_BIN` set in `make/local`, `~/.config/stan/make.local` or the environment moves the TBB the binary links against and not this field (§6). Recorded because Windows needs it at launch and a later `set_cmdstan_path()` must not move it (#1261 consumes it; no verdict here turns on it). Not compared: both routes it sees are compared already, through `cpp_options_supplied` and `builder` | -| `known_untracked_dependencies` | yes | no | reported (§6), never a trigger | +| `executable_hash` | yes | yes | hash of the executable this record describes | +| `cmdstan` | yes | yes | normalized installation path and version | +| `tbb_dir` | yes | **no** | the absolute TBB directory the call named, read as `make` receives the call's `cpp_options` (§3: last assignment wins, `FALSE` is an empty one): `TBB_LIB`, or `TBB_BIN` when `TBB_LIB` is empty, which is the order `compiler_flags` uses; resolved against the installation when relative, since `make` runs there; and the installation's own `lib/tbb` when the call named neither. Filled from the call, not asked of `make`: a `TBB_LIB` or `TBB_BIN` set in `make/local`, `~/.config/stan/make.local` or the environment moves the TBB the binary links against and not this field (§6). Recorded because Windows needs it at launch and a later `set_cmdstan_path()` must not move it (#1261 consumes it; no verdict here turns on it). Not compared: both routes it sees are compared already, through `cpp_options` and `cmdstan` | +| `untracked_dependencies` | yes | no | reported (§6), never a trigger | | `format_version` | yes | **no** | not a comparison: the reader either reads the record's version or does not, which is an artifact-side reason like unreadable JSON (§6) | @@ -888,7 +888,7 @@ Three consequences: **Recorded-but-not-compared is the ordinary case, not a list of exceptions.** The column says which, and it is not a short list. The default is not "everything in -`request` is compared", and reasoning from that default is what produced the errors. +`configuration` is compared", and reasoning from that default is what produced the errors. @@ -926,7 +926,7 @@ out of the code (§10). **What cmdstanr injects is itself build semantics.** The set is recorded rather than described here, so no list of injected options has to be kept correct in this -document. That is a statement about the `_injected` field, which is never compared, +document. That is a statement about the `stanc_options_added` field, which is never compared, and not about the injections themselves: whether the value an injection determines is compared is this table's question, and `--name` is the one that currently earns a row. @@ -935,7 +935,7 @@ row. **A change to which options cmdstanr injects does not rebuild anything already built.** An option a later cmdstanr adds can change the artifact while an old -record's `_supplied` goes on matching, and nothing rebuilds. That is the intended +record's `stanc_options` goes on matching, and nothing rebuilds. That is the intended answer: the caller asked for the same build they asked for before, and the new binary is theirs to ask for with `force_recompile = TRUE`. The scheduled case is `--filename-in-msg` (§9), which makes runtime exceptions name the real source rather @@ -946,7 +946,7 @@ models alone. CmdStan is not an exception to that rule. A CmdStan upgrade does rebuild, through -`builder`, because the installation is a standing runtime dependency of the artifact +`cmdstan`, because the installation is a standing runtime dependency of the artifact rather than a fact about how it was built: the binary loads its TBB through an absolute rpath, by default into that tree (§6), and re-resolution invokes that installation's stanc (§6). cmdstanr appears nowhere in the executable. It drives @@ -962,11 +962,11 @@ above rather than an exception to them.** Nothing cmdstanr injects is of that ki and the scheduled addition is not either; `--filename-in-msg` changes which file a runtime exception names. What keeps the class closed is that a correctness fix to generated code belongs to stanc, and a CmdStan upgrade already rebuilds through -`builder`. If a release ever needs one anyway, these are the rules it has to reopen, +`cmdstan`. If a release ever needs one anyway, these are the rules it has to reopen, because a NEWS entry cannot make incorrect reuse safe. Only `stanc_options` has an injected row. With the user header built as a flag -(§3), cmdstanr injects no C++ option at all, so a `cpp_options_injected` would be +(§3), cmdstanr injects no C++ option at all, so a `cpp_options_added` would be empty in every record 1.0 writes. If one ever appears it arrives with the field. **An injection nothing compares still applies.** `--name` is injected too, and its @@ -1209,7 +1209,7 @@ property is testable. **What the reader cannot use, it rejects as unreadable rather than working with.** A file that parses as JSON is not yet a record (§6). Every field the format requires -is checked for type and shape before the record is accepted, `builder`'s version +is checked for type and shape before the record is accepted, `cmdstan`'s version against the grammar §7 defines since a string that is not a CmdStan version is the wrong shape rather than an odd value, and a record failing any of those checks is unreadable whole: nothing in it is used and nothing in it is reported, including a @@ -1361,7 +1361,7 @@ executable was replaced (§2). single-configuration cache lets the most recent compile own the executable and the record beside it, so once another call or process rebuilds, the pair on disk is self-consistent and describes a program this object never saw. The path is -unchanged, the file exists, and the record's `artifact` hash matches the binary it +unchanged, the file exists, and the record's `executable_hash` matches the binary it now sits beside, which is the bond it exists to prove (§4). Nothing on disk disagrees, so the disagreement has to be carried in. For an executable-only object that carried-in hash is the whole check (§7). @@ -1675,7 +1675,7 @@ so this section can be read without holding the table open. Or when the record cannot be used at all: -- the executable does not match `artifact`: replaced by another process, or corrupt +- the executable does not match `executable_hash`: replaced by another process, or corrupt - the record is missing, unreadable, or written in a format version this cmdstanr does not read - the executable predates build records, so there is nothing to compare @@ -1825,7 +1825,7 @@ it does by name: `option -o cannot be repeated` for a `make/local` `-o` beside t it exists so that the build and `stanc --info` resolve the same files, and dropping the flag only when the call also supplies paths would leave the defect in place when it does not. Nothing recorded moves, since the call's options are in -`stanc_options_supplied` and `make/local` is hashed whole. Lands in Stage 1, where +`stanc_options` and `make/local` is hashed whole. Lands in Stage 1, where the boolean repeats already exist; the `--filename-in-msg` injection (§9) relies on it. @@ -1880,7 +1880,7 @@ source is identified by content and its directory is not compared; its basename a compiler input, since `R/model.R:835` passes it to stanc as `--name` and §3 makes the file name the only way to set that flag. So moving a project costs nothing while renaming `bernoulli.stan` to `survival.stan` costs a compile, for the same reason a -changed `stanc_options` entry does. §4's `request.stanc_name` row carries the +changed `stanc_options` entry does. §4's `configuration.stanc_name` row carries the argument. The user header's directory is the exception, for the reason given below. **Path-and-content identity is rejected, and it is the closest call here.** The @@ -1897,7 +1897,7 @@ Correct line, correct column, and whoever moved the project knows where it went. Against that, renaming a working directory from `docs/A` to `docs/B` would pay a full recompile for a benefit its user never receives, and nobody thinks of a directory name as a compiler input. Cross-machine moves almost always rebuild on -`builder` identity anyway, so path identity would be the sole trigger only for the +`cmdstan` identity anyway, so path identity would be the sole trigger only for the folder rename. The rule the rest of this section uses is: rebuild when the artifact would differ in a way the caller can observe and care about. It is why dependencies are hashed rather than trusted by mtime, and why `make/local` rebuilds even on an @@ -1947,7 +1947,7 @@ a lost record costs provenance rather than time. spelling, and nothing beneath it is tracked.** The `-I` flags a user puts in `cpp_options` are the explicit members of that set; the user header's own directory is the implicit one. The two are compared through different fields, the flags as -part of `request.cpp_options_supplied` and the header's path as the one dependency +part of `configuration.cpp_options` and the header's path as the one dependency whose recorded path is compared (§4), but this is one rule with two instances, not a rule plus an exception. @@ -2021,7 +2021,7 @@ refused once (§4). The comparison is the normalised installation path and the version, plus the `make/local` hash, which is its own dependency with its own trigger rather than -part of `builder`. +part of `cmdstan`. @@ -2065,7 +2065,7 @@ because the field is already recorded, and changes no verdict here. the record going bad: the record parses, it hash-binds to this binary, and `stan_build_info()` answers out of it. What it says is that the executable may not run, and whether anything can be done about that turns on the selected installation -rather than the recorded one. Select a different one and `builder` differs, so the +rather than the recorded one. Select a different one and `cmdstan` differs, so the ordinary trigger above has already fired and the model rebuilds against a CmdStan that exists. Leave the selection alone and the gone installation is also the one a rebuild would run in, so making this a trigger buys a doomed compile in place of @@ -2160,7 +2160,7 @@ they were, so that an unresolved set is never read as an empty one. One path reaches it: re-resolution is skipped when the selected -installation differs from `builder` (below). That difference is itself a trigger, +installation differs from `cmdstan` (below). That difference is itself a trigger, so the verdict is the same either way and only the reason list is shorter. @@ -2178,7 +2178,7 @@ against that installation. That is correct: `cmdstan_make_loc `install_cmdstan(overwrite = TRUE)` and the `-fPIC` auto-fix at `R/utils.R:932` all stale those executables, and the last of those fixes a bug for free, since today nothing notices. It is narrower than it first appears: an upgrade installs to a new -directory, so `builder` already differs. +directory, so `cmdstan` already differs. ### Include shadowing is detected, not accepted @@ -2229,10 +2229,10 @@ is free. -**Invoke stanc from the recorded `builder`, not from whichever installation is +**Invoke stanc from the recorded `cmdstan`, not from whichever installation is selected now**, or a different stanc's resolution rules get applied to a model this one did not build. **Check builder identity first**: if the selected installation -differs from `builder`, that is already a rebuild trigger (above) and should be +differs from `cmdstan`, that is already a rebuild trigger (above) and should be reported without attempting re-resolution at all. That leaves one way for the recorded stanc to be missing, the selection being the recorded installation and it being gone, and there the model can be neither assessed nor rebuilt, which is the @@ -2288,7 +2288,7 @@ channel, and not for a `make/local` include, which is not. -**The field is `known_untracked_dependencies`, not `provenance_complete`.** A regex +**The field is `untracked_dependencies`, not `provenance_complete`.** A regex can establish that a gap exists; it cannot establish that none does. Make also has variable expansion and `eval`; C++ has angle-bracket local headers, macro-expanded includes, line continuations and conditional inclusion. **No match means "no known @@ -2468,7 +2468,7 @@ provenance. -`$cpp_options()` returns the recorded `cpp_options_supplied` here, and +`$cpp_options()` returns the recorded `cpp_options` here, and `$user_header()` the recorded header path. That is consistent with §1: the accessor always answers "what was this build asked for", and adoption sources that answer from the record instead of from the current call. Since adoption hydrates from a @@ -2486,7 +2486,7 @@ to learn something the first fit establishes anyway, which is the cost **Executable without a usable record**: missing, unreadable (an unparseable -`builder` version among the field checks that decide it, §4), hash mismatch, or +`cmdstan` version among the field checks that decide it, §4), hash mismatch, or written in a format version this cmdstanr does not read. Explicitly unprovenanced, which is a statement about provenance and must not suppress what the binary does report. `stan_build_info()` returns an explicit unavailable provenance, never an @@ -2512,7 +2512,7 @@ does.** Adoption is the one place a version arrives from an a for; everywhere else it comes from the CmdStan installation the session validated at install time. So this is the only place the invariant §10 relies on can be established. A usable record's half is enforced where the record's other field -checks are (§4), so a record carrying an unparseable `builder` version is not a +checks are (§4), so a record carrying an unparseable `cmdstan` version is not a usable record; on the fallback, ` info` must report complete version fields. Failing both means the executable did not identify itself as a supported CmdStan @@ -2604,7 +2604,7 @@ every call, and cannot be silenced by fixing anything. `stan_build_info()` is ho caller asks. The line is not "standing properties are silent", since §6 does surface -`known_untracked_dependencies` at construction, and should. Nor is it whether the +`untracked_dependencies` at construction, and should. Nor is it whether the user chose the thing: including another makefile from `make/local` is deliberate, and CmdStan's own `make/local.example` ships it as a suggestion (§6). The line is whether the consequence follows from the action. @@ -2949,8 +2949,8 @@ that it returns "a parsed object" does not settle this: the obvious implementati is `jsonlite::fromJSON()` on the record, and then the returned object is the on-disk schema one deserialisation removed. That contradicts §4, which makes the format private and versions it so that it can change. A later cmdstanr that stores -`cpp_options_supplied` in a different shape bumps `format_version` and reshapes the -field, and every script reading `info$request$cpp_options_supplied` breaks on a +`cpp_options` in a different shape bumps `format_version` and reshapes the +field, and every script reading `info$configuration$cpp_options` breaks on a change §4 says is ours to make. So the reader translates: the public field names are the promise, and the record's layout is free underneath them. @@ -2968,13 +2968,13 @@ so §10's note that `stan_build_info()` is still a placeholder covers both. | field | present when | holds | |---|---|---| -| `provenance` | always | `status` and `reason`, both always present | +| `record` | always | `status` and `reason`, both always present | | `reported_features` | always | one entry per feature: four logical flags, each `TRUE`, `FALSE` or `NA`, and `stan_version`, a character scalar or `NA_character_` | | `format_version` | `unsupported_format` only (below) | the format the record was written in | -| `request` | provenance available | the recorded build configuration of §1 | -| `dependencies` | provenance available | every file whose content the build consumed | -| `builder` | provenance available | installation path, version, `exists` | -| `known_untracked_dependencies` | provenance available | §6's list; empty means nothing was detected | +| `configuration` | record available | the recorded build configuration of §1 | +| `dependencies` | record available | every file whose content the build consumed | +| `cmdstan` | record available | installation path, version, `exists` | +| `untracked_dependencies` | record available | §6's list; empty means nothing was detected | @@ -2987,9 +2987,9 @@ shipped yet, so the set can still be chosen freely; after 1.0 it cannot. The has fail that test. The artifact hash answers a question the caller can already answer by hashing the file whose path they just passed in, and the dependency hashes compare against nothing but another record's same field. So do -`stanc_options_injected` and `stanc_name`, which say how cmdstanr assembled the +`stanc_options_added` and `stanc_name`, which say how cmdstanr assembled the stanc command line rather than what was asked of it. `tbb_dir` is out on the same -test; the record keeps it because Windows needs it at launch (§4). `request` keeps +test; the record keeps it because Windows needs it at launch (§4). `configuration` keeps `include_paths` for diagnosis alone: a caller debugging an include has no other way to see where the build searched. @@ -3002,15 +3002,15 @@ that includes another makefile: ```r list( - provenance = list(status = "available", reason = NULL), + record = list(status = "available", reason = NULL), reported_features = list( stan_threads = TRUE, stan_mpi = FALSE, stan_opencl = FALSE, stan_no_range_checks = FALSE, stan_version = "2.39.0" ), - request = list( - cpp_options_supplied = list(STAN_THREADS = TRUE), - stanc_options_supplied = list(), - include_paths = "/proj" + configuration = list( + cpp_options = list(STAN_THREADS = TRUE), + stanc_options = list(), + include_paths = "/proj" ), dependencies = list( stan_file = list(built_from = "/proj/bernoulli.stan", exists = TRUE), @@ -3020,8 +3020,8 @@ list( user_header = NULL, make_local = list(built_from = "/cmdstan-2.39.0/make/local", exists = TRUE) ), - builder = list(path = "/cmdstan-2.39.0", version = "2.39.0", exists = TRUE), - known_untracked_dependencies = list( + cmdstan = list(path = "/cmdstan-2.39.0", version = "2.39.0", exists = TRUE), + untracked_dependencies = list( list(kind = "make_local_include", detected_in = "/cmdstan-2.39.0/make/local") ) ) @@ -3035,7 +3035,7 @@ not the one chosen. **The user header appears once, under `dependencies`.** It is a file the build -read, so it belongs beside the other files the build read rather than in `request` +read, so it belongs beside the other files the build read rather than in `configuration` with the options. §4 compares it as `dependencies.user_header.built_from` and the record holds it in that one place too, so nothing is translated here. The rule exists because carrying it in both is the natural thing to write, and it puts one @@ -3060,7 +3060,7 @@ declines to do, and a field for it would end up holding a path sometimes and a guess the rest of the time. That does repeat a path `dependencies` already holds, which the header rule above -forbids for `request`. The difference is that this field is never compared (§4), so +forbids for `configuration`. The difference is that this field is never compared (§4), so a stale copy cannot move a verdict, and an entry that names its own file is what lets the printer build its message from the entry alone. @@ -3101,22 +3101,22 @@ added here deliberately rather than appearing on its own. -**`provenance` carries why, not only whether.** §7 already enumerates four ways a +**`record` carries why, not only whether.** §7 already enumerates four ways a record fails to describe an executable, and collapsing them to a bare "unavailable" throws the distinction away at the only point a user can act on it: ```r -provenance = list(status = "available", reason = NULL) -provenance = list(status = "unavailable", reason = "record_missing") - # "record_unreadable" - # "artifact_mismatch" - # "unsupported_format" +record = list(status = "available", reason = NULL) +record = list(status = "unavailable", reason = "missing") + # "unreadable" + # "executable_mismatch" + # "unsupported_format" ``` Both names are always there. `available` requires `reason = NULL`, `unavailable` -requires exactly one code, and `names(provenance)` is the same pair either way, +requires exactly one code, and `names(record)` is the same pair either way, which is what a test can hold. The enum is machine-readable and no free-form message is stored. The printer derives its prose from the reason, so the wording stays revisable and never becomes contract. @@ -3128,7 +3128,7 @@ printer's only input: the direction message below is promised behaviour and `print.stan_build_info(x)` receives nothing but `x`, so the version has to reach it through the result. That is a named consumer, and it is what the fields withheld above do not have. The other three reasons carry no version, and -`record_unreadable` is the one to say out loud: an unreadable record is withheld +`unreadable` is the one to say out loud: an unreadable record is withheld whole (§4), so its version goes unreported even where it parsed perfectly well. @@ -3145,11 +3145,11 @@ for an older one. **Unknown and empty must never render alike, anywhere in the result.** This is §6's -`known_untracked_dependencies` rule and §1's absence-of-evidence rule stated once as +`untracked_dependencies` rule and §1's absence-of-evidence rule stated once as a property of the whole object rather than per field. An empty -`known_untracked_dependencies` means the scan detected nothing; no record to scan +`untracked_dependencies` means the scan detected nothing; no record to scan means the field is absent. A recorded builder whose path is gone is -`exists = FALSE`; an absent `builder` means there was no usable record to read one +`exists = FALSE`; an absent `cmdstan` means there was no usable record to read one from, which is the only way it can be missing. An unknown request is absent, not `list()`. @@ -3164,8 +3164,8 @@ unknown. **A readable record whose hash does not match is read only to say why.** -`artifact_mismatch` returns no record-derived field at all, even though `request`, -`dependencies` and `builder` all parsed. `reported_features` still comes back, read +`executable_mismatch` returns no record-derived field at all, even though `configuration`, +`dependencies` and `cmdstan` all parsed. `reported_features` still comes back, read off the executable rather than the record, which is the general rule below and not an exception to this one. This is the one place the reader holds back data it can see. Reporting the fields with a caveat is the natural instinct and it is wrong, @@ -3174,7 +3174,7 @@ validators to. A helpful partial report puts `stan_threads: true` from some othe build in front of a validator guarding this one, which is the silently single-threaded run this design exists to remove, arriving through a new door. Relocation never reaches here: a moved executable keeps its bytes and its hash, and -§6 compares dependencies by content, so `artifact_mismatch` means the executable at +§6 compares dependencies by content, so `executable_mismatch` means the executable at this path was replaced without cmdstanr writing a new record. @@ -3183,7 +3183,7 @@ this path was replaced without cmdstanr writing a new record. reasons are §7's "executable without a usable record", so all four read `reported_features` off the executable; an available one reads them from the record. That is one rule covering five states with nothing carved out of it, and -it is what keeps `artifact_mismatch` narrow: what a mismatched record loses is +it is what keeps `executable_mismatch` narrow: what a mismatched record loses is everything it claims about the build, not what the binary says about itself. A test has to prove where the features came from, not that the field is populated. @@ -3575,7 +3575,7 @@ would not even rebuild. So the recommendation needs a reason that does not depen on the identity rule. **The reason is that registering source hands the rebuild decision to the session, -and `builder` guarantees it fires.** instantiate's defining promise is that models +and `cmdstan` guarantees it fires.** instantiate's defining promise is that models compile at installation and never during use. §6 compares the CmdStan installation path and version, and `install_cmdstan()` puts every version in its own directory, so an upgrade changes both halves: @@ -3792,7 +3792,7 @@ variable, so by the time a record could be written the user's entries and cmdstanr's additions are indistinguishable. Do not fix that with a snapshot taken before line 673; it only works until someone adds a fifth injection site above it. Accumulate injections in their own list and merge the two when converting to -arguments, so `_supplied` and `_injected` are both values the code already holds +arguments, so `stanc_options` and `stanc_options_added` are both values the code already holds and neither is reconstructed. Getting this wrong is silent: it turns every injection into a compared option, and toggling `pedantic` starts recompiling. @@ -3811,7 +3811,7 @@ behaviour, different diagnosis, and the message has to say which happened. **Absence of evidence is not evidence of absence, twice.** `reported_features` is tri-state (§1): a feature CmdStan does not report is unknown, and treating unknown -as disabled reproduces #765 in a new place. `known_untracked_dependencies` (§6) is +as disabled reproduces #765 in a new place. `untracked_dependencies` (§6) is the same shape: an empty list means nothing was detected, never that the record is complete. Check for both rather than trusting the field names. diff --git a/tests/testthat/helper-build-record.R b/tests/testthat/helper-build-record.R index 4e4bc9b61..f752934ca 100644 --- a/tests/testthat/helper-build-record.R +++ b/tests/testthat/helper-build-record.R @@ -9,11 +9,11 @@ local_fake_exe <- function(name = "bernoulli") { example_record <- function(exe_file) { new_build_record( - request = list( - cpp_options_supplied = list(STAN_THREADS = "true"), - stanc_options_supplied = list("--O1"), - stanc_options_injected = list("--name=bernoulli_model"), - stanc_options_inherited = list(), + configuration = list( + cpp_options = list(STAN_THREADS = "true"), + stanc_options = list("--O1"), + stanc_options_added = list("--name=bernoulli_model"), + stanc_options_from_make = list(), stanc_name = "bernoulli", include_paths = list(dirname(exe_file)) ), @@ -29,23 +29,23 @@ example_record <- function(exe_file) { ), make_local = list(hash = "4b5a", built_from = "make/local") ), - artifact = hash_file(exe_file), - builder = list(path = "/opt/cmdstan-2.39.0", version = "2.39.0"), + executable_hash = hash_file(exe_file), + cmdstan = list(path = "/opt/cmdstan-2.39.0", version = "2.39.0"), tbb_dir = "/opt/cmdstan-2.39.0/stan/lib/stan_math/lib/tbb", - known_untracked_dependencies = list( + untracked_dependencies = list( list(kind = "make_local_include", detected_in = "make/local") ) ) } -example_expected <- function(record) { - list(request = record$request, artifact = NULL) +example_wanted <- function(record) { + list(configuration = record$configuration, executable_hash = NULL) } -example_observed <- function(record) { +example_current <- function(record) { list( record = list(status = "available", record = record), dependencies = record$dependencies, - builder = record$builder + cmdstan = record$cmdstan ) } diff --git a/tests/testthat/helper-envvars-and-paths.R b/tests/testthat/helper-envvars-and-paths.R index 763fbcf0b..2d28f8e7b 100644 --- a/tests/testthat/helper-envvars-and-paths.R +++ b/tests/testthat/helper-envvars-and-paths.R @@ -180,8 +180,9 @@ local_cmdstan_make_local <- function(cpp_options, envir = parent.frame(), } # The session's CmdStan version and, on a model object, the version it -# reports. The record beside the executable stays as written, since the -# guard compares it with the installation, not with either cached version. +# reports. The record beside the executable stays as written, since +# assert_current() compares it with the installation, not with either cached +# version. fake_cmdstan_version <- function(version, mod = NULL) { .cmdstanr$VERSION <- version if (!is.null(mod)) { diff --git a/tests/testthat/test-build-assess.R b/tests/testthat/test-build-assess.R index d9383e594..a58291a7e 100644 --- a/tests/testthat/test-build-assess.R +++ b/tests/testthat/test-build-assess.R @@ -1,23 +1,23 @@ test_that("a matching pair is current", { exe <- local_fake_exe() record <- example_record(exe) - expected <- example_expected(record) - observed <- example_observed(record) - expect_equal(assess_build(expected, observed), character(0)) + wanted <- example_wanted(record) + current <- example_current(record) + expect_equal(assess_build(wanted, current), character(0)) }) test_that("every changed row is reported, resolved dependencies included", { exe <- local_fake_exe() record <- example_record(exe) - expected <- example_expected(record) - observed <- example_observed(record) - expected$request$stanc_name <- "other_model" - observed$dependencies$stan_file$hash <- "1e0f" - observed$dependencies$included_files[[1]]$hash <- "3c2d" - observed$dependencies$user_header <- list(hash = "cccc", built_from = "h.hpp") - observed$dependencies$make_local$hash <- "5a4b" + wanted <- example_wanted(record) + current <- example_current(record) + wanted$configuration$stanc_name <- "other_model" + current$dependencies$stan_file$hash <- "1e0f" + current$dependencies$included_files[[1]]$hash <- "3c2d" + current$dependencies$user_header <- list(hash = "cccc", built_from = "h.hpp") + current$dependencies$make_local$hash <- "5a4b" expect_equal( - assess_build(expected, observed), + assess_build(wanted, current), c("stanc_name", "stan_file", "included_files", "user_header", "make_local") ) }) @@ -25,50 +25,50 @@ test_that("every changed row is reported, resolved dependencies included", { test_that("an unusable record is the only reason", { exe <- local_fake_exe() record <- example_record(exe) - expected <- example_expected(record) - observed <- example_observed(record) - expected$request$stanc_name <- "other_model" + wanted <- example_wanted(record) + current <- example_current(record) + wanted$configuration$stanc_name <- "other_model" reasons <- c( - "missing", "unreadable", "unsupported_format", "artifact_mismatch" + "missing", "unreadable", "unsupported_format", "executable_mismatch" ) for (reason in reasons) { - observed$record <- list(status = "unavailable", reason = reason) - expect_equal(assess_build(expected, observed), reason) + current$record <- list(status = "unavailable", reason = reason) + expect_equal(assess_build(wanted, current), reason) } }) test_that("a replaced executable is caught only by the object's own hash", { exe <- local_fake_exe() record <- example_record(exe) - expected <- example_expected(record) - observed <- example_observed(record) - expected$artifact <- "0000" - expect_equal(assess_build(expected, observed), "artifact") - expected$artifact <- NULL - expect_equal(assess_build(expected, observed), character(0)) + wanted <- example_wanted(record) + current <- example_current(record) + wanted$executable_hash <- "0000" + expect_equal(assess_build(wanted, current), "executable") + wanted$executable_hash <- NULL + expect_equal(assess_build(wanted, current), character(0)) }) test_that("unresolved dependencies are skipped, not read as empty", { exe <- local_fake_exe() record <- example_record(exe) - expected <- example_expected(record) - observed <- example_observed(record) - observed$dependencies <- NULL - observed$builder$path <- "/opt/cmdstan-2.40.0" - expect_equal(assess_build(expected, observed), "builder") - expected$request$stanc_name <- "other_model" - expect_equal(assess_build(expected, observed), c("stanc_name", "builder")) + wanted <- example_wanted(record) + current <- example_current(record) + current$dependencies <- NULL + current$cmdstan$path <- "/opt/cmdstan-2.40.0" + expect_equal(assess_build(wanted, current), "cmdstan") + wanted$configuration$stanc_name <- "other_model" + expect_equal(assess_build(wanted, current), c("stanc_name", "cmdstan")) }) -test_that("a gone builder is not a trigger", { +test_that("a gone CmdStan is not a trigger", { exe <- local_fake_exe() record <- example_record(exe) gone <- file.path(withr::local_tempdir(), "cmdstan") expect_false(dir.exists(gone)) - record$builder$path <- gone - expected <- example_expected(record) - observed <- example_observed(record) - expect_equal(assess_build(expected, observed), character(0)) - observed$builder$path <- withr::local_tempdir() - expect_equal(assess_build(expected, observed), "builder") + record$cmdstan$path <- gone + wanted <- example_wanted(record) + current <- example_current(record) + expect_equal(assess_build(wanted, current), character(0)) + current$cmdstan$path <- withr::local_tempdir() + expect_equal(assess_build(wanted, current), "cmdstan") }) diff --git a/tests/testthat/test-build-record-compile.R b/tests/testthat/test-build-record-compile.R index 91726fd2c..eb06098c1 100644 --- a/tests/testthat/test-build-record-compile.R +++ b/tests/testthat/test-build-record-compile.R @@ -29,12 +29,12 @@ test_that("a build writes a record that reads back available", { result <- read_build_record(mod$exe_file()) expect_equal(result$status, "available") - expect_equal(result$record$request$stanc_name, "bernoulli_model") + expect_equal(result$record$configuration$stanc_name, "bernoulli_model") expect_equal( - result$record$builder, + result$record$cmdstan, list(path = cmdstan_path(), version = cmdstan_version()) ) - expect_equal(result$record$artifact, hash_file(mod$exe_file())) + expect_equal(result$record$executable_hash, hash_file(mod$exe_file())) expect_false("user_header" %in% names(result$record$dependencies)) if (!file.exists(file.path(cmdstan_path(), "make", "local"))) { expect_false("make_local" %in% names(result$record$dependencies)) @@ -47,13 +47,14 @@ test_that("the recorded stanc name is the raw string stanc was passed", { mod <- mock_compile(stan_file) record <- read_build_record(mod$exe_file())$record - expect_equal(record$request$stanc_name, "my-model_model") + expect_equal(record$configuration$stanc_name, "my-model_model") expect_true( - "--name=my-model_model" %in% unlist(record$request$stanc_options_injected) + "--name=my-model_model" %in% + unlist(record$configuration$stanc_options_added) ) }) -test_that("supplied and injected stanc options are recorded apart", { +test_that("supplied and added stanc options are recorded apart", { stan_file <- local_bernoulli() mod <- mock_compile( stan_file, @@ -62,9 +63,9 @@ test_that("supplied and injected stanc options are recorded apart", { ) record <- read_build_record(mod$exe_file())$record - expect_equal(record$request$stanc_options_supplied, list("--O1")) + expect_equal(record$configuration$stanc_options, list("--O1")) expect_equal( - record$request$stanc_options_injected, + record$configuration$stanc_options_added, list( "--warn-pedantic", "--name=bernoulli_model", paste0("--filename-in-msg=", wsl_safe_path(mod$stan_file())) @@ -72,7 +73,7 @@ test_that("supplied and injected stanc options are recorded apart", { ) }) -test_that("cpp_options_supplied holds what the caller passed", { +test_that("cpp_options holds what the caller passed", { stan_file <- local_bernoulli() user_header <- withr::local_tempfile(lines = "", fileext = ".hpp") local_mocked_bindings( @@ -85,8 +86,8 @@ test_that("cpp_options_supplied holds what the caller passed", { ) record <- read_build_record(mod$exe_file())$record - expect_equal(record$request$cpp_options_supplied, list(STAN_THREADS = "TRUE")) - expect_false("USER_HEADER" %in% names(record$request$cpp_options_supplied)) + expect_equal(record$configuration$cpp_options, list(STAN_THREADS = "TRUE")) + expect_false("USER_HEADER" %in% names(record$configuration$cpp_options)) expect_equal( record$dependencies$user_header, list(hash = hash_file(user_header), built_from = resolve_path(user_header)) @@ -122,7 +123,7 @@ test_that("included files are recorded in stanc's order with content hashes", { } # The constructor defaults include_paths to the stan file's own directory. expect_equal( - record$request$include_paths, + record$configuration$include_paths, list(resolve_path(dirname(stan_file))) ) }) @@ -153,7 +154,7 @@ test_that("an include on the WSL filesystem is recorded by its share path", { expect_equal(included[[1]]$built_from, resolve_path(include)) }) -test_that("the other injection sites land in the injected list", { +test_that("the other injection sites land in the added list", { user_header <- withr::local_tempfile(lines = "", fileext = ".hpp") local_mocked_bindings( get_standalone_hpp = function(stan_file, stancflags, ...) "" @@ -167,13 +168,13 @@ test_that("the other injection sites land in the injected list", { record <- read_build_record(mod$exe_file())$record expect_equal( - record$request$stanc_options_injected, + record$configuration$stanc_options_added, list( "--use-opencl", "--allow-undefined", "--name=bernoulli_model", paste0("--filename-in-msg=", wsl_safe_path(mod$stan_file())) ) ) - expect_equal(record$request$stanc_options_supplied, list()) + expect_equal(record$configuration$stanc_options, list()) }) test_that("make/local is a dependency only when present", { @@ -260,7 +261,7 @@ test_that("a build with an untracked dependency records it", { record <- read_build_record(mod$exe_file())$record expect_equal( - record$known_untracked_dependencies, + record$untracked_dependencies, list(list(kind = "make_local_include", detected_in = make_local)) ) }) diff --git a/tests/testthat/test-build-record.R b/tests/testthat/test-build-record.R index 97288279b..2c32931d1 100644 --- a/tests/testthat/test-build-record.R +++ b/tests/testthat/test-build-record.R @@ -36,17 +36,17 @@ test_that("a written record reads back unchanged", { test_that("an empty object writes as {} and an empty array as []", { exe <- local_fake_exe() record <- example_record(exe) - record$request$cpp_options_supplied <- structure(list(), names = character()) + record$configuration$cpp_options <- structure(list(), names = character()) record$dependencies$included_files <- list() path <- write_build_record(record, exe) text <- paste(readLines(path, warn = FALSE), collapse = "\n") - expect_match(text, '"cpp_options_supplied"\\s*:\\s*\\{\\s*\\}') + expect_match(text, '"cpp_options"\\s*:\\s*\\{\\s*\\}') expect_match(text, '"included_files"\\s*:\\s*\\[\\s*\\]') result <- read_build_record(exe) expect_equal( - result$record$request$cpp_options_supplied, + result$record$configuration$cpp_options, structure(list(), names = character()) ) expect_equal(result$record$dependencies$included_files, list()) @@ -73,7 +73,7 @@ test_that("a record that is not JSON is unreadable", { test_that("a record with a field of the wrong type is unreadable", { exe <- local_fake_exe() record <- example_record(exe) - record$builder$version <- 42 + record$cmdstan$version <- 42 jsonlite::write_json( record, build_record_path(exe), auto_unbox = TRUE, pretty = TRUE, digits = NA @@ -89,7 +89,7 @@ test_that("a record repeating a member at its top level is unreadable", { exe <- local_fake_exe() json <- jsonlite::toJSON(example_record(exe), auto_unbox = TRUE, digits = NA) writeLines( - sub("}$", ",\"artifact\":\"different\"}", json), + sub("}$", ",\"executable_hash\":\"different\"}", json), build_record_path(exe) ) @@ -133,7 +133,7 @@ test_that("a record in a format we do not read is checked on its version alone", exe <- local_fake_exe() record <- example_record(exe) record$format_version <- 99L - record$builder <- "garbage" + record$cmdstan <- "garbage" jsonlite::write_json( record, build_record_path(exe), auto_unbox = TRUE, pretty = TRUE, digits = NA @@ -166,7 +166,7 @@ test_that("a record whose hash does not match the executable is a mismatch", { writeBin(as.raw(c(0x7f, 0x45, 0x4c, 0x46, 0x00)), exe) result <- read_build_record(exe) - expect_equal(result$reason, "artifact_mismatch") + expect_equal(result$reason, "executable_mismatch") expect_false("record" %in% names(result)) expect_false("format_version" %in% names(result)) }) @@ -210,36 +210,36 @@ test_that("the validator names the field that fails", { rebuild <- function(record) do.call(new_build_record, record[-1]) bad_version <- base - bad_version$builder$version <- "2.39" - expect_error(rebuild(bad_version), "`builder.version`", fixed = TRUE) + bad_version$cmdstan$version <- "2.39" + expect_error(rebuild(bad_version), "`cmdstan.version`", fixed = TRUE) no_name <- base - no_name$request$stanc_name <- "" - expect_error(rebuild(no_name), "`request.stanc_name`", fixed = TRUE) + no_name$configuration$stanc_name <- "" + expect_error(rebuild(no_name), "`configuration.stanc_name`", fixed = TRUE) logical_option <- base - logical_option$request$cpp_options_supplied <- list(STAN_THREADS = TRUE) + logical_option$configuration$cpp_options <- list(STAN_THREADS = TRUE) expect_error( rebuild(logical_option), - "`request.cpp_options_supplied.STAN_THREADS`", + "`configuration.cpp_options.STAN_THREADS`", fixed = TRUE ) repeated_option <- base - repeated_option$request$cpp_options_supplied <- list( + repeated_option$configuration$cpp_options <- list( STAN_THREADS = "false", STAN_THREADS = "true" ) expect_error( - rebuild(repeated_option), "`request.cpp_options_supplied`", fixed = TRUE + rebuild(repeated_option), "`configuration.cpp_options`", fixed = TRUE ) unknown_kind <- base - unknown_kind$known_untracked_dependencies <- list( + unknown_kind$untracked_dependencies <- list( list(kind = "mystery", detected_in = "make/local") ) expect_error( rebuild(unknown_kind), - "`known_untracked_dependencies[[1]].kind`", + "`untracked_dependencies[[1]].kind`", fixed = TRUE ) @@ -298,8 +298,8 @@ test_that("the hash catches what ordering cannot", { write_build_record(record_b, path) write_build_record(record_a, path) - expect_error(verify_build_record(path), "artifact_mismatch", fixed = TRUE) - expect_equal(read_build_record(path)$reason, "artifact_mismatch") + expect_error(verify_build_record(path), "executable_mismatch", fixed = TRUE) + expect_equal(read_build_record(path)$reason, "executable_mismatch") }) test_that("two identical build records compare with no differences", { @@ -313,16 +313,16 @@ test_that("a changed cpp option value differs as cpp_options", { exe <- local_fake_exe() recorded <- example_record(exe) current <- example_record(exe) - current$request$cpp_options_supplied <- list(STAN_THREADS = "false") + current$configuration$cpp_options <- list(STAN_THREADS = "false") expect_equal(compare_build_records(recorded, current), "cpp_options") }) -test_that("a reordered stanc_options_supplied differs as stanc_options", { +test_that("a reordered stanc_options differs as stanc_options", { exe <- local_fake_exe() recorded <- example_record(exe) current <- example_record(exe) - recorded$request$stanc_options_supplied <- list("--O0", "--O1") - current$request$stanc_options_supplied <- list("--O1", "--O0") + recorded$configuration$stanc_options <- list("--O0", "--O1") + current$configuration$stanc_options <- list("--O1", "--O0") expect_equal(compare_build_records(recorded, current), "stanc_options") }) @@ -330,8 +330,8 @@ test_that("a changed stanc option differs as stanc_options", { exe <- local_fake_exe() recorded <- example_record(exe) current <- example_record(exe) - recorded$request$stanc_options_supplied <- list("--O0") - current$request$stanc_options_supplied <- list("--O1") + recorded$configuration$stanc_options <- list("--O0") + current$configuration$stanc_options <- list("--O1") expect_equal(compare_build_records(recorded, current), "stanc_options") }) @@ -339,7 +339,7 @@ test_that("a changed stanc_name differs as stanc_name", { exe <- local_fake_exe() recorded <- example_record(exe) current <- example_record(exe) - current$request$stanc_name <- "other_model" + current$configuration$stanc_name <- "other_model" expect_equal(compare_build_records(recorded, current), "stanc_name") }) @@ -347,8 +347,8 @@ test_that("a rename stanc mangles to the same identifier still differs as stanc_ exe <- local_fake_exe() recorded <- example_record(exe) current <- example_record(exe) - recorded$request$stanc_name <- "my-model_model" - current$request$stanc_name <- "my_model_model" + recorded$configuration$stanc_name <- "my-model_model" + current$configuration$stanc_name <- "my_model_model" expect_equal(compare_build_records(recorded, current), "stanc_name") }) @@ -417,28 +417,28 @@ test_that("a changed make_local hash differs as make_local", { expect_equal(compare_build_records(recorded, current), "make_local") }) -test_that("a changed artifact differs as artifact", { +test_that("a changed executable hash differs as executable", { exe <- local_fake_exe() recorded <- example_record(exe) current <- example_record(exe) - current$artifact <- "deadbeef" - expect_equal(compare_build_records(recorded, current), "artifact") + current$executable_hash <- "deadbeef" + expect_equal(compare_build_records(recorded, current), "executable") }) -test_that("a changed builder version differs as builder", { +test_that("a changed cmdstan version differs as cmdstan", { exe <- local_fake_exe() recorded <- example_record(exe) current <- example_record(exe) - current$builder$version <- "2.40.0" - expect_equal(compare_build_records(recorded, current), "builder") + current$cmdstan$version <- "2.40.0" + expect_equal(compare_build_records(recorded, current), "cmdstan") }) -test_that("a changed builder path differs as builder", { +test_that("a changed cmdstan path differs as cmdstan", { exe <- local_fake_exe() recorded <- example_record(exe) current <- example_record(exe) - current$builder$path <- "/opt/cmdstan-2.40.0" - expect_equal(compare_build_records(recorded, current), "builder") + current$cmdstan$path <- "/opt/cmdstan-2.40.0" + expect_equal(compare_build_records(recorded, current), "cmdstan") }) test_that("two differences are both reported, in table order", { @@ -446,18 +446,18 @@ test_that("two differences are both reported, in table order", { recorded <- example_record(exe) current <- example_record(exe) current$dependencies$stan_file$hash <- "ffff" - current$builder$version <- "2.40.0" - expect_equal(compare_build_records(recorded, current), c("stan_file", "builder")) + current$cmdstan$version <- "2.40.0" + expect_equal(compare_build_records(recorded, current), c("stan_file", "cmdstan")) }) test_that("the same cpp options in a different assignment order do not differ", { exe <- local_fake_exe() recorded <- example_record(exe) current <- example_record(exe) - recorded$request$cpp_options_supplied <- list( + recorded$configuration$cpp_options <- list( STAN_THREADS = "true", STAN_NO_RANGE_CHECKS = "true" ) - current$request$cpp_options_supplied <- list( + current$configuration$cpp_options <- list( STAN_NO_RANGE_CHECKS = "true", STAN_THREADS = "true" ) expect_equal(compare_build_records(recorded, current), character(0)) @@ -489,22 +489,22 @@ test_that("differences outside the comparison table never count", { exe <- local_fake_exe() recorded <- example_record(exe) current <- example_record(exe) - current$request$stanc_options_injected <- list("--name=other_model") - current$request$include_paths <- list("/some/other/path") + current$configuration$stanc_options_added <- list("--name=other_model") + current$configuration$include_paths <- list("/some/other/path") current$reported_features$stan_opencl <- TRUE current$tbb_dir <- "/opt/other/tbb" - current$known_untracked_dependencies <- list( + current$untracked_dependencies <- list( list(kind = "user_header_include", detected_in = "other.hpp") ) expect_equal(compare_build_records(recorded, current), character(0)) }) -test_that("an injection added after the build does not rebuild", { +test_that("an option added after the build does not rebuild", { exe <- local_fake_exe() recorded <- example_record(exe) current <- example_record(exe) - current$request$stanc_options_injected <- c( - recorded$request$stanc_options_injected, + current$configuration$stanc_options_added <- c( + recorded$configuration$stanc_options_added, list("--filename-in-msg=/home/me/bernoulli.stan") ) expect_equal(compare_build_records(recorded, current), character(0)) diff --git a/tests/testthat/test-model-guard.R b/tests/testthat/test-model-guard.R index e63ccb5a1..2c336d669 100644 --- a/tests/testthat/test-model-guard.R +++ b/tests/testthat/test-model-guard.R @@ -4,12 +4,12 @@ set_cmdstan_path() # public member: whether it checks that the executable is still the one the # object was built against before it does anything else. member_class <- c( - sample = "guarded", sample_mpi = "guarded", optimize = "guarded", - laplace = "guarded", variational = "guarded", pathfinder = "guarded", - generate_quantities = "guarded", diagnose = "guarded", - cmdstan_defaults = "guarded", expose_functions = "guarded", - code = "snapshot", variables = "snapshot", print = "snapshot", - hpp_file = "snapshot", save_hpp_file = "snapshot", functions = "snapshot", + sample = "checked", sample_mpi = "checked", optimize = "checked", + laplace = "checked", variational = "checked", pathfinder = "checked", + generate_quantities = "checked", diagnose = "checked", + cmdstan_defaults = "checked", expose_functions = "checked", + code = "stored", variables = "stored", print = "stored", + hpp_file = "stored", save_hpp_file = "stored", functions = "stored", stan_file = "accessor", has_stan_file = "accessor", model_name = "accessor", exe_file = "accessor", include_paths = "accessor", cmdstan_version = "accessor", cpp_options = "accessor", @@ -53,23 +53,23 @@ test_that("every public member is classified, and only those", { expect_false("compile" %in% names(member_class)) }) -test_that("every guarded member raises the staleness error, bare", { +test_that("every checked method raises the staleness error, bare", { mod <- local_stale_model() - guarded <- names(member_class)[member_class == "guarded"] - for (name in guarded) { + checked <- names(member_class)[member_class == "checked"] + for (name in checked) { expect_error( mod[[name]](), class = "cmdstanr_stale_executable", info = name ) } }) -test_that("every non-guarded member gets past the guard", { +test_that("every method that is not checked works on a stale build", { mod <- local_stale_model() - non_guarded <- setdiff( - names(member_class)[member_class != "guarded"], + unchecked <- setdiff( + names(member_class)[member_class != "checked"], c("initialize", "clone", "functions", "print") ) - for (name in non_guarded) { + for (name in unchecked) { expect_true(not_stale(mod[[name]]()), info = name) } capture.output(expect_true(not_stale(mod$print()))) @@ -77,20 +77,20 @@ test_that("every non-guarded member gets past the guard", { expect_true(is.environment(mod$functions)) }) -test_that("the guard says what is stale and where to go", { +test_that("assert_current() says what is stale and where to go", { mod <- local_stale_model() expect_error(mod$sample(), "the Stan program changed", fixed = TRUE) expect_error(mod$sample(), "Run cmdstan_model() to rebuild it.", fixed = TRUE) }) -test_that("the guard is not memoised", { +test_that("assert_current() is not memoised", { mod <- local_stale_model() code <- readLines(mod$stan_file()) writeLines(code[-length(code)], mod$stan_file()) expect_true(not_stale(mod$cmdstan_defaults())) }) -test_that("a current model gets past the guard", { +test_that("a current model passes assert_current()", { stan_file <- write_stan_file( "parameters { real y; } model { y ~ std_normal(); }", dir = withr::local_tempdir() @@ -99,7 +99,7 @@ test_that("a current model gets past the guard", { expect_true(not_stale(mod$cmdstan_defaults())) }) -test_that("the guard names an altered or missing executable", { +test_that("assert_current() names an altered or missing executable", { stan_file <- write_stan_file( "parameters { real y; } model { y ~ std_normal(); }", dir = withr::local_tempdir() diff --git a/tests/testthat/test-model-rebuild-rules.R b/tests/testthat/test-model-rebuild-rules.R index b656f0383..48c18b306 100644 --- a/tests/testthat/test-model-rebuild-rules.R +++ b/tests/testthat/test-model-rebuild-rules.R @@ -104,7 +104,7 @@ test_that("stanc_options rebuild when they change, and pedantic never does", { cmdstan_model(stan_file, stanc_options = list("O1")) )) - # --warn-pedantic is injected rather than supplied, so it is not compared. + # --warn-pedantic is added rather than supplied, so it is not compared. mocked(expect_no_mock_compile( cmdstan_model(stan_file, stanc_options = list("O1"), pedantic = TRUE) )) @@ -247,9 +247,9 @@ test_that("a record naming another installation rebuilds", { mocked(expect_mock_compile(mod <- cmdstan_model(stan_file))) # The executable is untouched, so its hash still matches the record and the - # builder is the only row that differs. + # cmdstan is the only row that differs. record <- read_build_record(mod$exe_file())$record - record$builder$version <- "1.2.3" + record$cmdstan$version <- "1.2.3" write_build_record(record, mod$exe_file()) mocked(expect_mock_compile(expect_interactive_message( @@ -280,7 +280,8 @@ test_that("a CmdStan rebuilt in place at a newer version is a rebuild reason", { a <- mock_cmdstan_model(stan_file) writeLines("CMDSTAN_VERSION := 2.40.0", file.path(install_dir, "makefile")) - # The guard first, while the executable is still the one a was built with + # assert_current() first, while the executable is still the one a was + # built with expect_error( a$cmdstan_defaults(), "the selected CmdStan changed", class = "cmdstanr_stale_executable" @@ -377,7 +378,9 @@ test_that("an unusable record falls back to asking the executable", { writeLines("{", record_path) expect_asked() for (broken in list( - list(format_version = 99L), list(artifact = "wrong"), list(builder = "x") + list(format_version = 99L), + list(executable_hash = "wrong"), + list(cmdstan = "x") )) { record <- original record[names(broken)] <- broken @@ -417,7 +420,7 @@ test_that("a record member with a longer name is not read as the user header", { expect_null(b$user_header()) }) -test_that("filename-in-msg supplied unnamed is not injected again", { +test_that("filename-in-msg supplied unnamed is not added again", { stan_file <- local_bernoulli() mod <- mock_cmdstan_model( stan_file, stanc_options = list("filename-in-msg=published.stan") @@ -426,10 +429,10 @@ test_that("filename-in-msg supplied unnamed is not injected again", { record <- read_build_record(mod$exe_file())$record expect_true( "--filename-in-msg=published.stan" %in% - unlist(record$request$stanc_options_supplied) + unlist(record$configuration$stanc_options) ) expect_false(any(grepl( - "filename-in-msg", unlist(record$request$stanc_options_injected) + "filename-in-msg", unlist(record$configuration$stanc_options_added) ))) hpp <- paste(readLines(mod$hpp_file()), collapse = "\n") expect_match(hpp, "published.stan", fixed = TRUE) diff --git a/tests/testthat/test-model-rebuild.R b/tests/testthat/test-model-rebuild.R index 0e11192a4..fb9965efe 100644 --- a/tests/testthat/test-model-rebuild.R +++ b/tests/testthat/test-model-rebuild.R @@ -60,7 +60,7 @@ mod_b <- cmdstan_model(replaced_stan_file, force_recompile = TRUE) test_that("a replaced executable is refused by the object that built it", { expect_error( mod_a$cmdstan_defaults(), - "replaced after this model was created", fixed = TRUE, + "changed after this model was created", fixed = TRUE, class = "cmdstanr_stale_executable" ) expect_no_error(mod_b$cmdstan_defaults()) @@ -76,7 +76,7 @@ test_that("adoption from a record verifies by hash alone", { cmdstan_model(replaced_stan_file, force_recompile = TRUE) expect_error( mod_c$cmdstan_defaults(), - "replaced after this model was created", fixed = TRUE, + "changed after this model was created", fixed = TRUE, class = "cmdstanr_stale_executable" ) }) @@ -111,7 +111,7 @@ test_that("adoption without a record verifies by the hash it captured", { file.copy(bernoulli_exe, exe, overwrite = TRUE) expect_error( mod_d$cmdstan_defaults(), - "replaced after this model was created", fixed = TRUE, + "changed after this model was created", fixed = TRUE, class = "cmdstanr_stale_executable" ) }) @@ -141,7 +141,7 @@ test_that("an edited program with an old mtime still triggers a rebuild", { expect_error(mod$cmdstan_defaults(), class = "cmdstanr_stale_executable") }) -test_that("a re-resolution failure errors instead of producing a verdict", { +test_that("a failure resolving again errors instead of producing a verdict", { dir <- withr::local_tempdir() stan_file <- seed_from(canonical_include_stan, canonical_include_exe, dir) mod <- cmdstan_model(stan_file) @@ -160,7 +160,7 @@ test_that("a re-resolution failure errors instead of producing a verdict", { test_that("adoption from a record ignores a CmdStan it never selected", { record <- read_build_record(mod_b$exe_file())$record - record$builder$version <- "2.35.0" + record$cmdstan$version <- "2.35.0" write_build_record(record, mod_b$exe_file()) mod <- with_mocked_cli( @@ -379,16 +379,16 @@ test_that("log_prob after an edit still reflects the program that was built", { expect_equal(fit$log_prob(unconstrained_variables = 0.3), expected_lp) }) -test_that("a make/local pedantic flag is injected once, not inherited too", { +test_that("a pedantic flag both added and in make/local is recorded once, as added", { local_cmdstan_make_local(cpp_options = list("STANCFLAGS += --warn-pedantic")) stan_file <- local_program("bernoulli") mod <- mock_cmdstan_model(stan_file, pedantic = TRUE) record <- read_build_record(mod$exe_file())$record - injected <- unlist(record$request$stanc_options_injected) - inherited <- unlist(record$request$stanc_options_inherited) - expect_equal(sum(injected == "--warn-pedantic"), 1) - expect_false("--warn-pedantic" %in% inherited) + added <- unlist(record$configuration$stanc_options_added) + from_make <- unlist(record$configuration$stanc_options_from_make) + expect_equal(sum(added == "--warn-pedantic"), 1) + expect_false("--warn-pedantic" %in% from_make) expect_true(file.exists(mod$hpp_file())) }) diff --git a/tests/testthat/test-utils.R b/tests/testthat/test-utils.R index cc341d7f9..ca04c30c9 100644 --- a/tests/testthat/test-utils.R +++ b/tests/testthat/test-utils.R @@ -465,11 +465,11 @@ test_that("install_executable() restores both files if the pair fails verificati fixture <- local_exe_fixture() # A record that describes some other executable still writes, so only the # verification at the end of the transaction can catch it. - fixture$record$artifact <- "deadbeef" + fixture$record$executable_hash <- "deadbeef" expect_error( install_executable(fixture$from, fixture$to, fixture$record), - "artifact_mismatch", + "executable_mismatch", fixed = TRUE ) expect_identical(readLines(fixture$to), "old executable") diff --git a/tests/testthat/testthat-problems.rds b/tests/testthat/testthat-problems.rds new file mode 100644 index 0000000000000000000000000000000000000000..fbc2285e6383a222155114e7ad5b20729e3fff5a GIT binary patch literal 247499 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%0DyB{yhG8FSAY)tfz2dBc}%$iet10o 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 E0B756mH+?% literal 0 HcmV?d00001 From a87207a78b6533bf81e5f50c7a7fa19780dd8194 Mon Sep 17 00:00:00 2001 From: jgabry Date: Thu, 17 Sep 2026 18:05:40 -0600 Subject: [PATCH 2/2] Rename the build record's fields and the code around them Nothing has shipped, so the names can still change. The record's `request` is now `configuration`, with `cpp_options`, `stanc_options`, `stanc_options_added` and `stanc_options_from_make` inside it, since cmdstanr injects nothing into `cpp_options` and the plain names mean what the arguments mean. `artifact` is `executable_hash`, `builder` is `cmdstan`, `known_untracked_dependencies` is `untracked_dependencies`, and the reason for a record that does not match its executable is `executable_mismatch`. The public result's `provenance` becomes `record`. The code follows: `read_current_build()` replaces `observe_build()`, `assess_build()` takes what is wanted and what is current, `stancflags_added_by_make()` replaces `inherited_stancflags()`, and the facts a model keeps about its executable come from `facts_from_record()`. Comments and test titles drop the design doc's vocabulary where it named these things. Part of #1258. --- R/build.R | 171 ++++++++++---------- R/build_record.R | 104 ++++++------ R/model.R | 49 +++--- dev-notes/compilation-state-contract.md | 112 ++++++------- dev-notes/compilation-state.md | 174 ++++++++++----------- tests/testthat/helper-build-record.R | 24 +-- tests/testthat/helper-envvars-and-paths.R | 5 +- tests/testthat/test-build-assess.R | 74 ++++----- tests/testthat/test-build-record-compile.R | 33 ++-- tests/testthat/test-build-record.R | 94 +++++------ tests/testthat/test-model-guard.R | 34 ++-- tests/testthat/test-model-rebuild-rules.R | 19 ++- tests/testthat/test-model-rebuild.R | 20 +-- tests/testthat/test-utils.R | 4 +- 14 files changed, 469 insertions(+), 448 deletions(-) diff --git a/R/build.R b/R/build.R index 97e36ae20..86bec314f 100644 --- a/R/build.R +++ b/R/build.R @@ -3,12 +3,12 @@ #' Build or verify the executable for a Stan program #' -#' The one build path. The call is resolved into the request the record +#' The one build path. The call is resolved into the configuration the record #' compares, assess_build() says whether the executable beside the program (or #' in `dir`) was built from it, and a rebuild follows when it was not or when #' `force_recompile` asks for one. Both ways out generate the model's C++ from #' the source just verified or built, so a model constructed on a reused -#' executable holds the same snapshot as one that built it. +#' executable holds the same facts as one that built it. #' #' `force_recompile = NULL` means the caller did not say and the #' `cmdstanr_force_recompile` option decides. The rebuild reason names @@ -48,25 +48,25 @@ build_executable <- function(stan_file, # Options cmdstanr adds stay apart from the caller's, so the record can hold # each as it was, and are merged only when they become arguments. - injected <- list() + added <- list() if (pedantic) { - injected[["warn-pedantic"]] <- TRUE + added[["warn-pedantic"]] <- TRUE } if (isTRUE(cpp_option_value(cpp_options, "stan_opencl"))) { - injected[["use-opencl"]] <- TRUE + added[["use-opencl"]] <- TRUE } if (!is.null(user_header)) { - injected[["allow-undefined"]] <- TRUE + added[["allow-undefined"]] <- TRUE } - injected[["name"]] <- paste0(model_name_from_path(stan_file), "_model") + added[["name"]] <- paste0(model_name_from_path(stan_file), "_model") if (!stanc_option_supplied(stanc_options, "filename-in-msg")) { - injected[["filename-in-msg"]] <- wsl_safe_path(stan_file) + added[["filename-in-msg"]] <- wsl_safe_path(stan_file) } - request <- list( - cpp_options_supplied = parsed_cpp_options(cpp_options), - stanc_options_supplied = as.list(stanc_options_to_args(stanc_options)), - stanc_options_injected = as.list(stanc_options_to_args(injected)), - stanc_name = injected[["name"]], + configuration <- list( + cpp_options = parsed_cpp_options(cpp_options), + stanc_options = as.list(stanc_options_to_args(stanc_options)), + stanc_options_added = as.list(stanc_options_to_args(added)), + stanc_name = added[["name"]], include_paths = as.list(include_paths) ) @@ -77,19 +77,21 @@ build_executable <- function(stan_file, isTRUE(getOption("cmdstanr_force_recompile"))) { forced <- "force_recompile_option" } - observed <- observe_build(stan_file, include_paths, user_header, exe) + current <- read_current_build(stan_file, include_paths, user_header, exe) reasons <- c( - assess_build(list(request = request, artifact = NULL), observed), + assess_build( + list(configuration = configuration, executable_hash = NULL), current + ), forced ) rebuild <- length(reasons) > 0 if (rlang::is_interactive()) { - message(constructor_message(reasons, observed)) + message(constructor_message(reasons, current)) } # The flags stanc receives: the call's, then what make adds for this build. # On a reuse the record says what make added, since make/local is unchanged. - stancflags_call <- stanc_options_to_args(c(stanc_options, injected)) + stancflags_call <- stanc_options_to_args(c(stanc_options, added)) make_vars <- cpp_options_to_compile_flags(cpp_options) if (!is.null(user_header)) { make_vars <- c( @@ -97,17 +99,18 @@ build_executable <- function(stan_file, ) } if (rebuild) { - if (is.null(observed$info)) { - observed <- c( - observed, resolve_dependencies(stan_file, include_paths, user_header) + if (is.null(current$info)) { + current <- c( + current, resolve_dependencies(stan_file, include_paths, user_header) ) } - inherited <- inherited_stancflags(make_vars) + from_make <- stancflags_added_by_make(make_vars) } else { - inherited <- unlist(observed$record$record$request$stanc_options_inherited) + from_make <- + unlist(current$record$record$configuration$stanc_options_from_make) } - inherited <- drop_overridden_stancflags(inherited, stancflags_call) - stancflags_direct <- c(stancflags_call, inherited) + from_make <- drop_overridden_stancflags(from_make, stancflags_call) + stancflags_direct <- c(stancflags_call, from_make) stanc_inc_paths <- include_paths_stanc3_args( include_paths, direct_call = TRUE ) @@ -132,43 +135,44 @@ build_executable <- function(stan_file, ) if (!rebuild) { - record <- observed$record$record + record <- current$record$record } else { tmp_exe <- cmdstan_ext(strip_ext(source)) if (os_is_windows() && !os_is_wsl()) { tmp_exe <- utils::shortPathName(tmp_exe) } - # get_cmdstan_flags() split the inherited flags into words. Requote them + # get_cmdstan_flags() split the flags from make into words. Requote them # for the STANCFLAGS value handed back to make. stancflags_quoted <- stanc_options_to_args( - c(stanc_options, injected), quote_values = TRUE + c(stanc_options, added), quote_values = TRUE ) stancflags_make <- paste0( "STANCFLAGS += ", include_paths_stanc3_args(include_paths), paste0( - " ", c(stancflags_quoted, make_shell_quote(inherited)), collapse = "" + " ", c(stancflags_quoted, make_shell_quote(from_make)), collapse = "" ) ) run_make( c(wsl_safe_path(repair_path(tmp_exe)), make_vars, stancflags_make), quiet ) record <- new_build_record( - request = append( - request, list(stanc_options_inherited = as.list(inherited)), after = 3 + configuration = append( + configuration, list(stanc_options_from_make = as.list(from_make)), + after = 3 ), reported_features = reported_features_from_exe(tmp_exe), - dependencies = observed$dependencies, - artifact = hash_file(tmp_exe), - builder = observed$builder, + dependencies = current$dependencies, + executable_hash = hash_file(tmp_exe), + cmdstan = current$cmdstan, tbb_dir = tbb_dir_from_options(cpp_options), - known_untracked_dependencies = untracked_dependencies( - observed$dependencies$make_local$built_from, user_header + untracked_dependencies = untracked_dependencies( + current$dependencies$make_local$built_from, user_header ) ) leftover_backup <- install_executable(tmp_exe, exe, record) # Said once, when the record is written, and never on a no-op. - if (length(record$known_untracked_dependencies) > 0) { - message(untracked_dependencies_note(record$known_untracked_dependencies)) + if (length(record$untracked_dependencies) > 0) { + message(untracked_dependencies_note(record$untracked_dependencies)) } if (!is.null(leftover_backup)) { warning( @@ -182,7 +186,7 @@ build_executable <- function(stan_file, exe_file = exe, record = record, include_paths = include_paths, - info = observed$info, + info = current$info, hpp_code = hpp_code ) } @@ -192,16 +196,18 @@ build_executable <- function(stan_file, #' Three outcomes. With a usable record beside it nothing is launched: the #' hash the reader checked proves the binary is the one the record describes. #' Without one the executable is asked to identify itself with `info`, once. A -#' version it reports admits it, unprovenanced. No version refuses it, since an -#' executable that cannot say what built it is not a CmdStan executable. +#' version it reports admits it, without a record. No version refuses it, +#' since an executable that cannot say what built it is not a CmdStan +#' executable. #' -#' @return A list: `record` (`NULL` when unprovenanced), `reported_features`, -#' `version` and `artifact`, the executable's hash. +#' @return A list: `record` (`NULL` when there is no record), +#' `reported_features`, `version` and `executable_hash`, the executable's +#' hash. #' @noRd adopt_executable <- function(exe_file) { found <- read_build_record(exe_file) if (found$status == "available") { - return(snapshot_from_record(found$record)) + return(facts_from_record(found$record)) } features <- reported_features_from_exe(exe_file) if (is.null(features[["stan_version"]])) { @@ -215,50 +221,51 @@ adopt_executable <- function(exe_file) { record = NULL, reported_features = features, version = features[["stan_version"]], - artifact = hash_file(exe_file) + executable_hash = hash_file(exe_file) ) } -snapshot_from_record <- function(record) { +facts_from_record <- function(record) { list( record = record, reported_features = record$reported_features, - version = record$builder$version, - artifact = record$artifact + version = record$cmdstan$version, + executable_hash = record$executable_hash ) } #' What is on disk for an executable built from a Stan program #' -#' The `observed` argument of assess_build(): the record beside the executable, +#' The `current` argument of assess_build(): the record beside the executable, #' the installation selected now, and the sources hashed the way the writer #' hashes them, with `info`, the `stanc --info` output they were resolved -#' from, kept for the snapshot. The constructor and the guard both come here, -#' so they cannot assemble it differently. The sources are resolved through -#' the selected stanc, so they are left unresolved when the selection is not -#' the recorded builder. That difference is a reason on its own. +#' from, kept for the facts. The constructor and assert_current() both come +#' here, so they cannot assemble it differently. The sources are resolved +#' through the selected stanc, so they are left unresolved when the selection +#' is not the recorded CmdStan. That difference is a reason on its own. #' #' @noRd -observe_build <- function(stan_file, include_paths, user_header, exe_file) { - observed <- list( +read_current_build <- function(stan_file, include_paths, user_header, + exe_file) { + current <- list( exe_file = exe_file, record = list(status = "unavailable", reason = "no_executable"), - builder = list(path = cmdstan_path(), version = current_cmdstan_version()) + cmdstan = list(path = cmdstan_path(), version = current_cmdstan_version()) ) if (file.exists(exe_file)) { - observed$record <- read_build_record(exe_file) + current$record <- read_build_record(exe_file) } - same_builder <- function() { - recorded <- observed$record$record - differs <- compare_build_records(recorded, observed, "builder") + same_cmdstan <- function() { + recorded <- current$record$record + differs <- compare_build_records(recorded, current, "cmdstan") length(differs) == 0 } - if (observed$record$status == "available" && same_builder()) { - observed <- c( - observed, resolve_dependencies(stan_file, include_paths, user_header) + if (current$record$status == "available" && same_cmdstan()) { + current <- c( + current, resolve_dependencies(stan_file, include_paths, user_header) ) } - observed + current } #' Hash what a build of this program consumes @@ -295,10 +302,10 @@ resolve_dependencies <- function(stan_file, include_paths, user_header) { #' What Make resolves `STANCFLAGS` to with this build's variables applied, #' which is how make/local and CmdStan's own makefiles reach stanc. An include #' path there is refused: `include_paths` is the one channel, so that -#' re-resolution sees every path the build saw. +#' resolving again sees every path the build saw. #' #' @noRd -inherited_stancflags <- function(make_vars) { +stancflags_added_by_make <- function(make_vars) { flags <- get_cmdstan_flags("STANCFLAGS", make_vars) is_include_path <- grepl("--include-paths", flags, fixed = TRUE) | startsWith(flags, "-I") @@ -418,12 +425,12 @@ model_name_from_path <- function(path) { } -# what the constructor and the guard say ------------------------------------ +# what the constructor and assert_current() say ----------------------------- #' What the constructor says before it builds or reuses #' #' @noRd -constructor_message <- function(reasons, observed) { +constructor_message <- function(reasons, current) { if (length(reasons) == 0) { return("Model executable is up to date!") } @@ -431,7 +438,7 @@ constructor_message <- function(reasons, observed) { return("Compiling Stan program...") } paste( - c("Recompiling:", paste0(" - ", rebuild_reasons(reasons, observed))), + c("Recompiling:", paste0(" - ", rebuild_reasons(reasons, current))), collapse = "\n" ) } @@ -439,12 +446,12 @@ constructor_message <- function(reasons, observed) { #' Word the reasons assess_build() returns, one line each #' #' @noRd -rebuild_reasons <- function(reasons, observed) { - recorded <- observed$record$record - current <- observed$dependencies +rebuild_reasons <- function(reasons, current) { + recorded <- current$record$record + deps <- current$dependencies included_files <- function() { old <- recorded$dependencies$included_files - new <- current$included_files + new <- deps$included_files if (length(old) != length(new)) { return("the set of included files changed") } @@ -457,7 +464,7 @@ rebuild_reasons <- function(reasons, observed) { paste0("included files changed (", paste(paths, collapse = ", "), ")") } format_version <- function() { - written <- observed$record$format_version + written <- current$record$format_version sprintf( paste0( "the build record was written by %s version of cmdstanr (format %s; ", @@ -472,7 +479,7 @@ rebuild_reasons <- function(reasons, observed) { switch( reason, no_executable = paste0( - "there is no executable at '", observed$exe_file, "'" + "there is no executable at '", current$exe_file, "'" ), missing = paste0( "the executable has no build record, so what it was built with ", @@ -483,11 +490,11 @@ rebuild_reasons <- function(reasons, observed) { "it was built with cannot be verified" ), unsupported_format = format_version(), - artifact_mismatch = paste0( + executable_mismatch = paste0( "the executable does not match its build record, so it was replaced ", "or altered after it was built" ), - artifact = "the executable was replaced after this model was created", + executable = "the executable changed after this model was created", cpp_options = "`cpp_options` changed", stanc_options = "`stanc_options` changed", stanc_name = "the model name changed", @@ -495,21 +502,21 @@ rebuild_reasons <- function(reasons, observed) { included_files = included_files(), user_header = paste0( "the user header changed (", - (current$user_header %||% recorded$dependencies$user_header)$built_from, + (deps$user_header %||% recorded$dependencies$user_header)$built_from, ")" ), make_local = paste0( "make/local changed (", - (current$make_local %||% recorded$dependencies$make_local)$built_from, + (deps$make_local %||% recorded$dependencies$make_local)$built_from, ")" ), - builder = sprintf( + cmdstan = sprintf( paste0( "the selected CmdStan changed (built with %s at '%s'; ", "%s at '%s' is selected now)" ), - recorded$builder$version, recorded$builder$path, - observed$builder$version, observed$builder$path + recorded$cmdstan$version, recorded$cmdstan$path, + current$cmdstan$version, current$cmdstan$path ), force_recompile = "`force_recompile = TRUE` was supplied", force_recompile_option = "the `cmdstanr_force_recompile` option is set" @@ -518,7 +525,7 @@ rebuild_reasons <- function(reasons, observed) { vapply(reasons, line, character(1), USE.NAMES = FALSE) } -#' The error a guarded member raises on a stale executable +#' The error a checked method raises on a stale executable #' #' Carries the class `cmdstanr_stale_executable` so callers can catch it by #' what it means rather than by its text. diff --git a/R/build_record.R b/R/build_record.R index 62fb6737b..5c6dfb045 100644 --- a/R/build_record.R +++ b/R/build_record.R @@ -120,34 +120,38 @@ validate_build_record <- function(record) { ) } - request <- record_member(record, "request", "object") + configuration <- record_member(record, "configuration", "object") cpp_options <- record_member( - request, "cpp_options_supplied", "object", "request.cpp_options_supplied" + configuration, "cpp_options", "object", "configuration.cpp_options" ) for (i in seq_along(cpp_options)) { option_name <- names(cpp_options)[[i]] - field <- paste0("request.cpp_options_supplied.", option_name) + field <- paste0("configuration.cpp_options.", option_name) if (!grepl(paste0("^", make_variable_name_pattern, "$"), option_name)) { stop_build_record_field(field, "must be named for a Make variable") } record_shape(cpp_options[[i]], "string", field) } record_string_array( - request, "stanc_options_supplied", "request.stanc_options_supplied" + configuration, "stanc_options", "configuration.stanc_options" ) record_string_array( - request, "stanc_options_injected", "request.stanc_options_injected" + configuration, "stanc_options_added", + "configuration.stanc_options_added" ) record_string_array( - request, "stanc_options_inherited", "request.stanc_options_inherited" + configuration, "stanc_options_from_make", + "configuration.stanc_options_from_make" ) stanc_name <- record_member( - request, "stanc_name", "string", "request.stanc_name" + configuration, "stanc_name", "string", "configuration.stanc_name" ) if (!nzchar(stanc_name)) { - stop_build_record_field("request.stanc_name", "must not be empty") + stop_build_record_field("configuration.stanc_name", "must not be empty") } - record_string_array(request, "include_paths", "request.include_paths") + record_string_array( + configuration, "include_paths", "configuration.include_paths" + ) reported_features <- record_member(record, "reported_features", "object") for (i in seq_along(reported_features)) { @@ -173,23 +177,23 @@ validate_build_record <- function(record) { ) } - record_member(record, "artifact", "string") + record_member(record, "executable_hash", "string") - builder <- record_member(record, "builder", "object") - record_member(builder, "path", "string", "builder.path") - version <- record_member(builder, "version", "string", "builder.version") + cmdstan <- record_member(record, "cmdstan", "object") + record_member(cmdstan, "path", "string", "cmdstan.path") + version <- record_member(cmdstan, "version", "string", "cmdstan.version") # A string that is not a CmdStan version is the wrong shape, not an odd value. if (!grepl(cmdstan_version_pattern, version)) { stop_build_record_field( - "builder.version", "must be a CmdStan version such as \"2.39.0\"" + "cmdstan.version", "must be a CmdStan version such as \"2.39.0\"" ) } record_member(record, "tbb_dir", "string") - untracked <- record_member(record, "known_untracked_dependencies", "array") + untracked <- record_member(record, "untracked_dependencies", "array") for (i in seq_along(untracked)) { - field <- paste0("known_untracked_dependencies[[", i, "]]") + field <- paste0("untracked_dependencies[[", i, "]]") entry <- record_shape(untracked[[i]], "object", field) kind <- record_member(entry, "kind", "string", paste0(field, ".kind")) if (!kind %in% c("make_local_include", "user_header_include")) { @@ -210,23 +214,23 @@ validate_build_record <- function(record) { #' #' The one place a record is built. `format_version` comes first and the rest #' follow the schema's order, so the written JSON reads in that order too. -#' `request` arrives in the forms the record compares: `cpp_options_supplied` -#' as canonical Make assignments, one per name, and the three stanc option +#' `configuration` arrives in the forms the record compares: `cpp_options` +#' as normalized Make assignments, one per name, and the three stanc option #' lists as the argument vectors stanc receives. #' #' @noRd -new_build_record <- function(request, reported_features, dependencies, artifact, - builder, tbb_dir, - known_untracked_dependencies = list()) { +new_build_record <- function(configuration, reported_features, dependencies, + executable_hash, cmdstan, tbb_dir, + untracked_dependencies = list()) { record <- list( format_version = build_record_format_version, - request = request, + configuration = configuration, reported_features = reported_features, dependencies = dependencies, - artifact = artifact, - builder = builder, + executable_hash = executable_hash, + cmdstan = cmdstan, tbb_dir = tbb_dir, - known_untracked_dependencies = known_untracked_dependencies + untracked_dependencies = untracked_dependencies ) validate_build_record(record) record @@ -410,8 +414,8 @@ read_build_record <- function(exe_file) { if (!accepted) { return(unreadable) } - if (!identical(hash_file(exe_file), record[["artifact"]])) { - return(list(status = "unavailable", reason = "artifact_mismatch")) + if (!identical(hash_file(exe_file), record[["executable_hash"]])) { + return(list(status = "unavailable", reason = "executable_mismatch")) } list(status = "available", record = record) @@ -444,11 +448,11 @@ verify_build_record <- function(exe_file) { #' @noRd build_record_comparisons <- list( cpp_options = function(x) { - supplied <- x[["request"]][["cpp_options_supplied"]] + supplied <- x[["configuration"]][["cpp_options"]] supplied[order(names(supplied))] }, - stanc_options = function(x) x[["request"]][["stanc_options_supplied"]], - stanc_name = function(x) x[["request"]][["stanc_name"]], + stanc_options = function(x) x[["configuration"]][["stanc_options"]], + stanc_name = function(x) x[["configuration"]][["stanc_name"]], stan_file = function(x) x[["dependencies"]][["stan_file"]][["hash"]], included_files = function(x) { lapply(x[["dependencies"]][["included_files"]], `[[`, "hash") @@ -457,8 +461,8 @@ build_record_comparisons <- list( x[["dependencies"]][["user_header"]][c("hash", "built_from")] }, make_local = function(x) x[["dependencies"]][["make_local"]]["hash"], - artifact = function(x) x[["artifact"]], - builder = function(x) x[["builder"]][c("path", "version")] + executable = function(x) x[["executable_hash"]], + cmdstan = function(x) x[["cmdstan"]][c("path", "version")] ) #' Compare a recorded build against the current one @@ -481,42 +485,42 @@ compare_build_records <- function(recorded, current, #' Decide whether an executable is current #' -#' Takes two lists and compares them. `expected` is what the caller wants -#' the executable to have been built from. Its `request` holds the options -#' this call would record. Its `artifact` is the hash the object was built -#' against, or `NULL` at the constructor, which has no expectation yet. -#' `observed` is what is there now. Its `record` is what +#' Takes two lists and compares them. `wanted` is what the caller wants +#' the executable to have been built from. Its `configuration` holds the +#' options this call would record. Its `executable_hash` is the hash the +#' object was built against, or `NULL` at the constructor, which has no +#' expectation yet. `current` is what is there now. Its `record` is what #' `read_build_record()` returned. Its `dependencies` are the current files #' hashed the way the writer hashes them, or `NULL` when nobody resolved -#' them. Its `builder` is the installation selected now. +#' them. Its `cmdstan` is the installation selected now. #' #' Returns a character vector of reasons to rebuild, empty when the #' executable is current. When the record cannot be used the vector holds #' that one reason and nothing else, because there is no baseline to compare #' the rest against. Otherwise it names every compared row that differs. #' The dependency rows are skipped when nobody resolved them, so an -#' unresolved set is never mistaken for an empty one. The expected artifact +#' unresolved set is never mistaken for an empty one. The wanted executable #' hash is what catches an executable another process rebuilt, since the #' record beside it then matches it and nothing on disk disagrees. Reads no #' file and runs nothing. #' #' @noRd -assess_build <- function(expected, observed) { - if (observed$record$status != "available") { - return(observed$record$reason) +assess_build <- function(wanted, current) { + if (current$record$status != "available") { + return(current$record$reason) } - recorded <- observed$record$record - current <- list( - request = expected$request, - dependencies = observed$dependencies, - artifact = expected$artifact %||% recorded$artifact, - builder = observed$builder + recorded <- current$record$record + now <- list( + configuration = wanted$configuration, + dependencies = current$dependencies, + executable_hash = wanted$executable_hash %||% recorded$executable_hash, + cmdstan = current$cmdstan ) rows <- names(build_record_comparisons) - if (is.null(observed$dependencies)) { + if (is.null(current$dependencies)) { rows <- setdiff( rows, c("stan_file", "included_files", "user_header", "make_local") ) } - compare_build_records(recorded, current, rows) + compare_build_records(recorded, now, rows) } diff --git a/R/model.R b/R/model.R index c6cc8694f..f713e465e 100644 --- a/R/model.R +++ b/R/model.R @@ -347,7 +347,7 @@ CmdStanModel <- R6::R6Class( include_paths_ = NULL, user_header_ = NULL, exe_file_ = character(), - artifact_ = NULL, + executable_hash_ = NULL, record_ = NULL, reported_features_ = NULL, cmdstan_version_ = NULL, @@ -366,46 +366,51 @@ CmdStanModel <- R6::R6Class( paste0("The executable at '", exe, "' no longer exists.") ) } - if (!identical(hash_file(exe), private$artifact_)) { + if (!identical(hash_file(exe), private$executable_hash_)) { stop_stale_executable(paste0( "The executable at '", exe, - "' was replaced after this model was created." + "' changed after this model was created." )) } return(invisible(self)) } assert_stan_file_exists(private$stan_file_) - observed <- observe_build( + current <- read_current_build( private$stan_file_, private$include_paths_, private$user_header_, exe ) reasons <- assess_build( - list(request = private$record_$request, artifact = private$artifact_), - observed + list( + configuration = private$record_$configuration, + executable_hash = private$executable_hash_ + ), + current ) if (length(reasons) > 0) { stop_stale_executable(c( "The executable is out of date:", - paste0(" - ", rebuild_reasons(reasons, observed)), + paste0(" - ", rebuild_reasons(reasons, current)), "Run cmdstan_model() to rebuild it." )) } invisible(self) }, - # The standalone-functions C++, generated from the source once, on the - # first call that has passed the guard, when the source is known to be - # the built one. Construction does not pay a stanc run for a feature most - # models never use. Fits copy it from here. Empty without a source. + # The standalone-functions C++, generated from the source once, after + # assert_current() has passed, when the source is known to be the built + # one. Construction does not pay a stanc run for a feature most models + # never use. Fits copy it from here. Empty without a source. standalone_functions = function() { if (self$has_stan_file() && is.null(self$functions$hpp_code)) { - request <- private$record_$request + configuration <- private$record_$configuration self$functions$hpp_code <- get_standalone_hpp( private$stan_file_, c("--standalone-functions", include_paths_stanc3_args( private$include_paths_, direct_call = TRUE ), - unlist(request[c("stanc_options_supplied", "stanc_options_injected", - "stanc_options_inherited")], use.names = FALSE)) + unlist(configuration[c( + "stanc_options", "stanc_options_added", + "stanc_options_from_make" + )], use.names = FALSE)) ) } self$functions @@ -448,7 +453,7 @@ CmdStanModel <- R6::R6Class( writeLines(built$hpp_code, private$hpp_file_) private$model_methods_env_ <- new.env() private$model_methods_env_$hpp_code_ <- built$hpp_code - snapshot <- snapshot_from_record(built$record) + facts <- facts_from_record(built$record) } else { assert_no_build_args_for_exe_only( cpp_options, stanc_options, include_paths, user_header, @@ -458,14 +463,14 @@ CmdStanModel <- R6::R6Class( assert_file_exists(exe_file, access = "r", extension = ext) private$exe_file_ <- resolve_path(exe_file) private$model_name_ <- model_name_from_path(private$exe_file_) - snapshot <- adopt_executable(private$exe_file_) + facts <- adopt_executable(private$exe_file_) } - private$record_ <- snapshot$record - private$artifact_ <- snapshot$artifact - private$reported_features_ <- snapshot$reported_features - private$cmdstan_version_ <- snapshot$version + private$record_ <- facts$record + private$executable_hash_ <- facts$executable_hash + private$reported_features_ <- facts$reported_features + private$cmdstan_version_ <- facts$version private$user_header_ <- - snapshot$record$dependencies[["user_header"]][["built_from"]] + facts$record$dependencies[["user_header"]][["built_from"]] invisible(self) }, include_paths = function() { @@ -511,7 +516,7 @@ CmdStanModel <- R6::R6Class( private$cmdstan_version_ }, cpp_options = function() { - private$record_$request$cpp_options_supplied %||% + private$record_$configuration$cpp_options %||% structure(list(), names = character()) }, user_header = function() { diff --git a/dev-notes/compilation-state-contract.md b/dev-notes/compilation-state-contract.md index 122969a37..ad52fbb02 100644 --- a/dev-notes/compilation-state-contract.md +++ b/dev-notes/compilation-state-contract.md @@ -10,12 +10,12 @@ it. ## [1. Vocabulary: what the record is, and what it is not](compilation-state.md#1-vocabulary-what-the-record-is-and-what-it-is-not) -The record describes how an executable came to exist. It is not a configuration -store, it does not authorise whatever happens to be at the executable path, and it -does not replace looking at the binary itself. Its fields are different kinds of -fact: +The record describes how an executable came to exist. It cannot be fed back into +a build, it does not authorise whatever happens to be at the executable path, and +it does not replace looking at the binary itself. Its fields are different kinds +of fact: -- **`request`**: the build configuration. `stanc_options` is stored two ways, what +- **`configuration`**: what the build was asked for. `stanc_options` is stored two ways, what the caller supplied and what cmdstanr injected. The two are disjoint because cmdstanr injects only what the caller did not supply. Which list a value lands in is decided by where it came from; whether it can force a rebuild is decided per @@ -26,16 +26,16 @@ fact: explain a build. Feeding them back into another build is not supported and no rule here depends on it. - **`reported_features`**: what the binary reports as enabled. Kept apart from - `request` because `make/local` can enable threading or OpenCL the user never - mentioned. `request` is everything settled before the build ran; `reported_features` + `configuration` because `make/local` can enable threading or OpenCL the user never + mentioned. `configuration` is everything settled before the build ran; `reported_features` is what could only be discovered afterward. - **`dependencies`**: the sources consumed, and enough about how they were resolved to resolve them again. Identified by content; each also records the `built_from` path it had at build time (§4). -- **`artifact`**: a hash of the executable this record describes, used only to check - that a record and an executable belong together (§4). -- **`builder`**: the CmdStan installation that produced it. -- **`known_untracked_dependencies`**: dependencies we can see exist but cannot +- **`executable_hash`**: a hash of the executable this record describes, used only to + check that a record and an executable belong together (§4). +- **`cmdstan`**: the CmdStan installation that produced it. +- **`untracked_dependencies`**: dependencies we can see exist but cannot resolve (§6). An empty list means nothing was detected, never that the record is complete. - **`format_version`**: which format the record is written in. 1.0 reads only the @@ -51,7 +51,7 @@ never be read as disabled.** only when the state is known, and let an absent key mean unknown. **Request and reported features are never merged into one accessor.** -`$cpp_options()` reports `cpp_options_supplied`, what the caller asked for and not +`$cpp_options()` reports `cpp_options`, what the caller asked for and not what cmdstanr added. The user header has its own accessor, `$user_header()`, matching its own argument; it is not readable through `$cpp_options()` because it is no longer settable there (§3). `stan_build_info()` reports what the binary says, with its @@ -235,33 +235,33 @@ contains.** | Field | Recorded | Compared | Notes | |---|---|---|---| -| `request.cpp_options_supplied` | yes | yes | what the caller passed; canonicalized per field (§3, #1250) | -| `request.stanc_options_supplied` | yes | yes | as above | -| `request.stanc_options_injected` | yes | **no** | what cmdstanr added, disjoint from `_supplied` by construction. Never compared as a list; whether an injection's effect is compared is decided per field like every other row, and the model name is the one that earns its own, below | -| `request.stanc_options_inherited` | yes | **no** | the `STANCFLAGS` make added for the build, as passed to make after the call's own flags displaced their make/local copies (§6). A reuse regenerates the model's C++ (§5) with them, instead of asking make again on every construction. Not compared: `make/local` is, and what an included makefile or the environment adds is untracked (§6) | -| `request.stanc_name` | yes | **yes** | the `--name` stanc receives, which `R/model.R:835` derives from the file name; §3 rejects the `stanc_options` spelling, so this is the only source. The build bakes it into the binary, and no other compared field pins it down, since content hashes are compared and paths are not. Its visible effect is the CSV header (`R/csv.R:873`), which carries both the raw value stanc was passed and the mangled one stanc compiled | -| `request.include_paths`, effective | yes | **no** | the paths in force for the call drive re-resolution (§6): this call's at the constructor, the object's own at a guarded method, never the recorded ones (§5). The recorded value is provenance | +| `configuration.cpp_options` | yes | yes | what the caller passed; canonicalized per field (§3, #1250) | +| `configuration.stanc_options` | yes | yes | as above | +| `configuration.stanc_options_added` | yes | **no** | what cmdstanr added, disjoint from `stanc_options` by construction. Never compared as a list; whether an injection's effect is compared is decided per field like every other row, and the model name is the one that earns its own, below | +| `configuration.stanc_options_from_make` | yes | **no** | the `STANCFLAGS` make added for the build, as passed to make after the call's own flags displaced their make/local copies (§6). A reuse regenerates the model's C++ (§5) with them, instead of asking make again on every construction. Not compared: `make/local` is, and what an included makefile or the environment adds is untracked (§6) | +| `configuration.stanc_name` | yes | **yes** | the `--name` stanc receives, which `R/model.R:835` derives from the file name; §3 rejects the `stanc_options` spelling, so this is the only source. The build bakes it into the binary, and no other compared field pins it down, since content hashes are compared and paths are not. Its visible effect is the CSV header (`R/csv.R:873`), which carries both the raw value stanc was passed and the mangled one stanc compiled | +| `configuration.include_paths`, effective | yes | **no** | the paths in force for the call drive re-resolution (§6): this call's at the constructor, the object's own at a guarded method, never the recorded ones (§5). The recorded value is provenance | | `reported_features` | yes | no | describes the binary; never a trigger (§1) | | `dependencies[].hash` | yes | yes | content hash; this is what identity means | | `dependencies[].built_from` | yes | no | where the file was at build time; provenance. The user header is the exception below | | `dependencies.user_header.built_from` | yes | **yes** | the one *dependency* path compared, because the C++ closure beneath it cannot be enumerated. `-I` flags decide the same resolution and are compared inside `cpp_options` above (§6) | | `dependencies.included_files` | yes | yes | **ordered sequence**, duplicates preserved (§6) | -| `artifact` | yes | yes | hash of the executable this record describes | -| `builder` | yes | yes | normalized installation path and version | -| `tbb_dir` | yes | **no** | the absolute TBB directory the call named, read as `make` receives the call's `cpp_options` (§3: last assignment wins, `FALSE` is an empty one): `TBB_LIB`, or `TBB_BIN` when `TBB_LIB` is empty, which is the order `compiler_flags` uses; resolved against the installation when relative, since `make` runs there; and the installation's own `lib/tbb` when the call named neither. Filled from the call, not asked of `make`: a `TBB_LIB` or `TBB_BIN` set in `make/local`, `~/.config/stan/make.local` or the environment moves the TBB the binary links against and not this field (§6). Recorded because Windows needs it at launch and a later `set_cmdstan_path()` must not move it (#1261 consumes it; no verdict here turns on it). Not compared: both routes it sees are compared already, through `cpp_options_supplied` and `builder` | -| `known_untracked_dependencies` | yes | no | reported (§6), never a trigger | +| `executable_hash` | yes | yes | hash of the executable this record describes | +| `cmdstan` | yes | yes | normalized installation path and version | +| `tbb_dir` | yes | **no** | the absolute TBB directory the call named, read as `make` receives the call's `cpp_options` (§3: last assignment wins, `FALSE` is an empty one): `TBB_LIB`, or `TBB_BIN` when `TBB_LIB` is empty, which is the order `compiler_flags` uses; resolved against the installation when relative, since `make` runs there; and the installation's own `lib/tbb` when the call named neither. Filled from the call, not asked of `make`: a `TBB_LIB` or `TBB_BIN` set in `make/local`, `~/.config/stan/make.local` or the environment moves the TBB the binary links against and not this field (§6). Recorded because Windows needs it at launch and a later `set_cmdstan_path()` must not move it (#1261 consumes it; no verdict here turns on it). Not compared: both routes it sees are compared already, through `cpp_options` and `cmdstan` | +| `untracked_dependencies` | yes | no | reported (§6), never a trigger | | `format_version` | yes | **no** | not a comparison: the reader either reads the record's version or does not, which is an artifact-side reason like unreadable JSON (§6) | **Origin is stored, not inferred.** **A change to which options cmdstanr injects does not rebuild anything already built.** An option a later cmdstanr adds can change the artifact while an old -record's `_supplied` goes on matching, and nothing rebuilds. That is the intended +record's `stanc_options` goes on matching, and nothing rebuilds. That is the intended answer: the caller asked for the same build they asked for before, and the new binary is theirs to ask for with `force_recompile = TRUE`. CmdStan is not an exception to that rule. A CmdStan upgrade does rebuild, through -`builder`, because the installation is a standing runtime dependency of the artifact +`cmdstan`, because the installation is a standing runtime dependency of the artifact rather than a fact about how it was built: the binary loads its TBB through an absolute rpath, by default into that tree (§6), and re-resolution invokes that installation's stanc (§6). @@ -318,7 +318,7 @@ of one destination is unsupported; locking is tracked separately. **What the reader cannot use, it rejects as unreadable rather than working with.** A file that parses as JSON is not yet a record (§6). Every field the format requires -is checked for type and shape before the record is accepted, `builder`'s version +is checked for type and shape before the record is accepted, `cmdstan`'s version against the grammar §7 defines since a string that is not a CmdStan version is the wrong shape rather than an odd value, and a record failing any of those checks is unreadable whole: nothing in it is used and nothing in it is reported, including a @@ -507,7 +507,7 @@ marks **compared** differs from what this call computes. Which fields those are Or when the record cannot be used at all: -- the executable does not match `artifact`: replaced by another process, or corrupt +- the executable does not match `executable_hash`: replaced by another process, or corrupt - the record is missing, unreadable, or written in a format version this cmdstanr does not read - the executable predates build records, so there is nothing to compare @@ -630,7 +630,7 @@ models the regex detects. The comparison is the normalised installation path and the version, plus the `make/local` hash, which is its own dependency with its own trigger rather than -part of `builder`. +part of `cmdstan`. **A different path at the same version is a rebuild reason.** @@ -664,7 +664,7 @@ different executable would supply the wrong baseline. they were, so that an unresolved set is never read as an empty one. One path reaches it: re-resolution is skipped when the selected -installation differs from `builder` (below). That difference is itself a trigger, +installation differs from `cmdstan` (below). That difference is itself a trigger, so the verdict is the same either way and only the reason list is shorter. `make/local` is per-installation, so editing it invalidates every model built @@ -682,10 +682,10 @@ provenance (§4). **Re-resolve by invoking stanc, never by reimplementing its rules.** -**Invoke stanc from the recorded `builder`, not from whichever installation is +**Invoke stanc from the recorded `cmdstan`, not from whichever installation is selected now**, or a different stanc's resolution rules get applied to a model this one did not build. **Check builder identity first**: if the selected installation -differs from `builder`, that is already a rebuild trigger (above) and should be +differs from `cmdstan`, that is already a rebuild trigger (above) and should be reported without attempting re-resolution at all. **Normalisation: normalised absolute paths, recorded but not compared.** @@ -712,7 +712,7 @@ In both cases a regex, `^\s*(?:-?include|sinclude)\b` for `make/local` and `^\s*#\s*include\s*"` for the user header, tells us there is an untracked dependency, without resolving anything. -**The field is `known_untracked_dependencies`, not `provenance_complete`.** +**The field is `untracked_dependencies`, not `provenance_complete`.** **No match means "no known gap", never "complete".** @@ -778,7 +778,7 @@ freshness may still be unverifiable. If the recorded sources are absent or the paths no longer resolve, say so specifically rather than collapsing it to unknown provenance. -`$cpp_options()` returns the recorded `cpp_options_supplied` here, and +`$cpp_options()` returns the recorded `cpp_options` here, and `$user_header()` the recorded header path. **Adoption establishes what the artifact is, not that it runs.** A hash-matched @@ -787,7 +787,7 @@ this machine adopts successfully and fails when something first runs it, with th launch error §6 requires. **Executable without a usable record**: missing, unreadable (an unparseable -`builder` version among the field checks that decide it, §4), hash mismatch, or +`cmdstan` version among the field checks that decide it, §4), hash mismatch, or written in a format version this cmdstanr does not read. Explicitly unprovenanced, which is a statement about provenance and must not suppress what the binary does report. `stan_build_info()` returns an explicit unavailable provenance, never an @@ -954,13 +954,13 @@ are the promise, and the record's layout is free underneath them. | field | present when | holds | |---|---|---| -| `provenance` | always | `status` and `reason`, both always present | +| `record` | always | `status` and `reason`, both always present | | `reported_features` | always | one entry per feature: four logical flags, each `TRUE`, `FALSE` or `NA`, and `stan_version`, a character scalar or `NA_character_` | | `format_version` | `unsupported_format` only (below) | the format the record was written in | -| `request` | provenance available | the recorded build configuration of §1 | -| `dependencies` | provenance available | every file whose content the build consumed | -| `builder` | provenance available | installation path, version, `exists` | -| `known_untracked_dependencies` | provenance available | §6's list; empty means nothing was detected | +| `configuration` | record available | the recorded build configuration of §1 | +| `dependencies` | record available | every file whose content the build consumed | +| `cmdstan` | record available | installation path, version, `exists` | +| `untracked_dependencies` | record available | §6's list; empty means nothing was detected | **A field is public only if a caller can act on it.** @@ -971,15 +971,15 @@ that includes another makefile: ```r list( - provenance = list(status = "available", reason = NULL), + record = list(status = "available", reason = NULL), reported_features = list( stan_threads = TRUE, stan_mpi = FALSE, stan_opencl = FALSE, stan_no_range_checks = FALSE, stan_version = "2.39.0" ), - request = list( - cpp_options_supplied = list(STAN_THREADS = TRUE), - stanc_options_supplied = list(), - include_paths = "/proj" + configuration = list( + cpp_options = list(STAN_THREADS = TRUE), + stanc_options = list(), + include_paths = "/proj" ), dependencies = list( stan_file = list(built_from = "/proj/bernoulli.stan", exists = TRUE), @@ -989,8 +989,8 @@ list( user_header = NULL, make_local = list(built_from = "/cmdstan-2.39.0/make/local", exists = TRUE) ), - builder = list(path = "/cmdstan-2.39.0", version = "2.39.0", exists = TRUE), - known_untracked_dependencies = list( + cmdstan = list(path = "/cmdstan-2.39.0", version = "2.39.0", exists = TRUE), + untracked_dependencies = list( list(kind = "make_local_include", detected_in = "/cmdstan-2.39.0/make/local") ) ) @@ -1018,18 +1018,18 @@ are the four booleans ` info` prints, `stan_threads`, `stan_mpi`, `stan_opencl` and `stan_no_range_checks`, plus `stan_version`, and the table above has their types. They are always all present. -**`provenance` carries why, not only whether.** +**`record` carries why, not only whether.** ```r -provenance = list(status = "available", reason = NULL) -provenance = list(status = "unavailable", reason = "record_missing") - # "record_unreadable" - # "artifact_mismatch" - # "unsupported_format" +record = list(status = "available", reason = NULL) +record = list(status = "unavailable", reason = "missing") + # "unreadable" + # "executable_mismatch" + # "unsupported_format" ``` Both names are always there. `available` requires `reason = NULL`, `unavailable` -requires exactly one code, and `names(provenance)` is the same pair either way, +requires exactly one code, and `names(record)` is the same pair either way, which is what a test can hold. The enum is machine-readable and no free-form message is stored. @@ -1045,15 +1045,15 @@ for an older one. **Unknown and empty must never render alike, anywhere in the result.** An empty -`known_untracked_dependencies` means the scan detected nothing; no record to scan +`untracked_dependencies` means the scan detected nothing; no record to scan means the field is absent. A recorded builder whose path is gone is -`exists = FALSE`; an absent `builder` means there was no usable record to read one +`exists = FALSE`; an absent `cmdstan` means there was no usable record to read one from, which is the only way it can be missing. An unknown request is absent, not `list()`. **A readable record whose hash does not match is read only to say why.** -`artifact_mismatch` returns no record-derived field at all, even though `request`, -`dependencies` and `builder` all parsed. `reported_features` still comes back, read +`executable_mismatch` returns no record-derived field at all, even though `configuration`, +`dependencies` and `cmdstan` all parsed. `reported_features` still comes back, read off the executable rather than the record, which is the general rule below and not an exception to this one. diff --git a/dev-notes/compilation-state.md b/dev-notes/compilation-state.md index ac47bd963..fe6cd552b 100644 --- a/dev-notes/compilation-state.md +++ b/dev-notes/compilation-state.md @@ -32,7 +32,7 @@ known about an executable cmdstanr did not build. **Out of scope:** the toolchain itself, meaning the compiler version and system libraries, which are untracked (§6). The CmdStan installation is in scope: its -normalised path and version together are the `builder` identity, and §6 also checks +normalised path and version together are the `cmdstan` identity, and §6 also checks that the installation still exists. --- @@ -75,12 +75,12 @@ that build are `cmdstan_model()` and `compile_stan_file()` (§8). -The record describes how an executable came to exist. It is not a configuration -store, it does not authorise whatever happens to be at the executable path, and it -does not replace looking at the binary itself. Its fields are different kinds of -fact: +The record describes how an executable came to exist. It cannot be fed back into +a build, it does not authorise whatever happens to be at the executable path, and +it does not replace looking at the binary itself. Its fields are different kinds +of fact: -- **`request`**: the build configuration. `stanc_options` is stored two ways, what +- **`configuration`**: what the build was asked for. `stanc_options` is stored two ways, what the caller supplied and what cmdstanr injected. The two are disjoint because cmdstanr injects only what the caller did not supply. Which list a value lands in is decided by where it came from; whether it can force a rebuild is decided per @@ -91,16 +91,16 @@ fact: explain a build. Feeding them back into another build is not supported and no rule here depends on it. - **`reported_features`**: what the binary reports as enabled. Kept apart from - `request` because `make/local` can enable threading or OpenCL the user never - mentioned. `request` is everything settled before the build ran; `reported_features` + `configuration` because `make/local` can enable threading or OpenCL the user never + mentioned. `configuration` is everything settled before the build ran; `reported_features` is what could only be discovered afterward. - **`dependencies`**: the sources consumed, and enough about how they were resolved to resolve them again. Identified by content; each also records the `built_from` path it had at build time (§4). -- **`artifact`**: a hash of the executable this record describes, used only to check - that a record and an executable belong together (§4). -- **`builder`**: the CmdStan installation that produced it. -- **`known_untracked_dependencies`**: dependencies we can see exist but cannot +- **`executable_hash`**: a hash of the executable this record describes, used only to + check that a record and an executable belong together (§4). +- **`cmdstan`**: the CmdStan installation that produced it. +- **`untracked_dependencies`**: dependencies we can see exist but cannot resolve (§6). An empty list means nothing was detected, never that the record is complete. - **`format_version`**: which format the record is written in. 1.0 reads only the @@ -137,7 +137,7 @@ schema; this is the constraint it satisfies. **Request and reported features are never merged into one accessor.** -`$cpp_options()` reports `cpp_options_supplied`, what the caller asked for and not +`$cpp_options()` reports `cpp_options`, what the caller asked for and not what cmdstanr added. The user header has its own accessor, `$user_header()`, matching its own argument; it is not readable through `$cpp_options()` because it is no longer settable there (§3). `stan_build_info()` reports what the binary says, with its @@ -484,7 +484,7 @@ there is no other argument to redirect to. **`$user_header()` is added**, so the dedicated argument has a dedicated accessor. Today the only way to read the header back is `$cpp_options()[["USER_HEADER"]]`. -That is why §1 can have `$cpp_options()` report `cpp_options_supplied` without +That is why §1 can have `$cpp_options()` report `cpp_options` without losing anything: the header was never really a `cpp_option`, and now it is not one at all. @@ -493,12 +493,12 @@ writes the header back into `cpp_options` under whichever spelling was used, and `:941` then stores that list, so a caller who passed `user_header = "inc/mine.hpp"` as an argument and never touched `cpp_options` gets `USER_HEADER = "/abs/path/inc/mine.hpp"` back from `$cpp_options()`. Wired to -`cpp_options_supplied` with that line still in place, the accessor would report a +`cpp_options` with that line still in place, the accessor would report a field the caller never passed, holding a path they never wrote. What survives is only the Make flag: CmdStan reads `-include $(USER_HEADER)` (`make/program:41`), so `USER_HEADER=` still has to reach `make`. **It reaches it as a flag built with the others, not as a recorded `cpp_options` entry.** A recorded option would put the -header's path in `request` as well as in `dependencies` (§8), and under WSL not +header's path in `configuration` as well as in `dependencies` (§8), and under WSL not even in the same spelling, since the Make side is `wsl_safe_path()`-transformed (`R/utils.R:627`) and `built_from` is not. `resolved_header$spelling` goes with the line, since `R/model.R:709` is its only consumer and one channel has one @@ -564,7 +564,7 @@ a source-backed model whose executable already exists. Today that is the only ch there is: `cmdstan_model(f, cpp_options = list(stan_threads = TRUE))` against an unthreaded executable warns from it, and twelve assertions in three test files expect the warning. From Stage 4 the engine compares the request against the record's -`cpp_options_supplied` and rebuilds on a difference (§6), so a request-against-report +`cpp_options` and rebuilds on a difference (§6), so a request-against-report diff has no job left, and with only an executable §7 makes the request an error. The helper goes in the pull request that wires the engine (#1255), with its branch and its tests, which turn from expecting the warning into expecting the rebuild. @@ -865,21 +865,21 @@ must not restate it. A rule written in two places is a future inconsistency. | Field | Recorded | Compared | Notes | |---|---|---|---| -| `request.cpp_options_supplied` | yes | yes | what the caller passed; canonicalized per field (§3, #1250) | -| `request.stanc_options_supplied` | yes | yes | as above | -| `request.stanc_options_injected` | yes | **no** | what cmdstanr added, disjoint from `_supplied` by construction. Never compared as a list; whether an injection's effect is compared is decided per field like every other row, and the model name is the one that earns its own, below | -| `request.stanc_options_inherited` | yes | **no** | the `STANCFLAGS` make added for the build, as passed to make after the call's own flags displaced their make/local copies (§6). A reuse regenerates the model's C++ (§5) with them, instead of asking make again on every construction. Not compared: `make/local` is, and what an included makefile or the environment adds is untracked (§6) | -| `request.stanc_name` | yes | **yes** | the `--name` stanc receives, which `R/model.R:835` derives from the file name; §3 rejects the `stanc_options` spelling, so this is the only source. The build bakes it into the binary, and no other compared field pins it down, since content hashes are compared and paths are not. Its visible effect is the CSV header (`R/csv.R:873`), which carries both the raw value stanc was passed and the mangled one stanc compiled | -| `request.include_paths`, effective | yes | **no** | the paths in force for the call drive re-resolution (§6): this call's at the constructor, the object's own at a guarded method, never the recorded ones (§5). The recorded value is provenance | +| `configuration.cpp_options` | yes | yes | what the caller passed; canonicalized per field (§3, #1250) | +| `configuration.stanc_options` | yes | yes | as above | +| `configuration.stanc_options_added` | yes | **no** | what cmdstanr added, disjoint from `stanc_options` by construction. Never compared as a list; whether an injection's effect is compared is decided per field like every other row, and the model name is the one that earns its own, below | +| `configuration.stanc_options_from_make` | yes | **no** | the `STANCFLAGS` make added for the build, as passed to make after the call's own flags displaced their make/local copies (§6). A reuse regenerates the model's C++ (§5) with them, instead of asking make again on every construction. Not compared: `make/local` is, and what an included makefile or the environment adds is untracked (§6) | +| `configuration.stanc_name` | yes | **yes** | the `--name` stanc receives, which `R/model.R:835` derives from the file name; §3 rejects the `stanc_options` spelling, so this is the only source. The build bakes it into the binary, and no other compared field pins it down, since content hashes are compared and paths are not. Its visible effect is the CSV header (`R/csv.R:873`), which carries both the raw value stanc was passed and the mangled one stanc compiled | +| `configuration.include_paths`, effective | yes | **no** | the paths in force for the call drive re-resolution (§6): this call's at the constructor, the object's own at a guarded method, never the recorded ones (§5). The recorded value is provenance | | `reported_features` | yes | no | describes the binary; never a trigger (§1) | | `dependencies[].hash` | yes | yes | content hash; this is what identity means | | `dependencies[].built_from` | yes | no | where the file was at build time; provenance. The user header is the exception below | | `dependencies.user_header.built_from` | yes | **yes** | the one *dependency* path compared, because the C++ closure beneath it cannot be enumerated. `-I` flags decide the same resolution and are compared inside `cpp_options` above (§6) | | `dependencies.included_files` | yes | yes | **ordered sequence**, duplicates preserved (§6) | -| `artifact` | yes | yes | hash of the executable this record describes | -| `builder` | yes | yes | normalized installation path and version | -| `tbb_dir` | yes | **no** | the absolute TBB directory the call named, read as `make` receives the call's `cpp_options` (§3: last assignment wins, `FALSE` is an empty one): `TBB_LIB`, or `TBB_BIN` when `TBB_LIB` is empty, which is the order `compiler_flags` uses; resolved against the installation when relative, since `make` runs there; and the installation's own `lib/tbb` when the call named neither. Filled from the call, not asked of `make`: a `TBB_LIB` or `TBB_BIN` set in `make/local`, `~/.config/stan/make.local` or the environment moves the TBB the binary links against and not this field (§6). Recorded because Windows needs it at launch and a later `set_cmdstan_path()` must not move it (#1261 consumes it; no verdict here turns on it). Not compared: both routes it sees are compared already, through `cpp_options_supplied` and `builder` | -| `known_untracked_dependencies` | yes | no | reported (§6), never a trigger | +| `executable_hash` | yes | yes | hash of the executable this record describes | +| `cmdstan` | yes | yes | normalized installation path and version | +| `tbb_dir` | yes | **no** | the absolute TBB directory the call named, read as `make` receives the call's `cpp_options` (§3: last assignment wins, `FALSE` is an empty one): `TBB_LIB`, or `TBB_BIN` when `TBB_LIB` is empty, which is the order `compiler_flags` uses; resolved against the installation when relative, since `make` runs there; and the installation's own `lib/tbb` when the call named neither. Filled from the call, not asked of `make`: a `TBB_LIB` or `TBB_BIN` set in `make/local`, `~/.config/stan/make.local` or the environment moves the TBB the binary links against and not this field (§6). Recorded because Windows needs it at launch and a later `set_cmdstan_path()` must not move it (#1261 consumes it; no verdict here turns on it). Not compared: both routes it sees are compared already, through `cpp_options` and `cmdstan` | +| `untracked_dependencies` | yes | no | reported (§6), never a trigger | | `format_version` | yes | **no** | not a comparison: the reader either reads the record's version or does not, which is an artifact-side reason like unreadable JSON (§6) | @@ -888,7 +888,7 @@ Three consequences: **Recorded-but-not-compared is the ordinary case, not a list of exceptions.** The column says which, and it is not a short list. The default is not "everything in -`request` is compared", and reasoning from that default is what produced the errors. +`configuration` is compared", and reasoning from that default is what produced the errors. @@ -926,7 +926,7 @@ out of the code (§10). **What cmdstanr injects is itself build semantics.** The set is recorded rather than described here, so no list of injected options has to be kept correct in this -document. That is a statement about the `_injected` field, which is never compared, +document. That is a statement about the `stanc_options_added` field, which is never compared, and not about the injections themselves: whether the value an injection determines is compared is this table's question, and `--name` is the one that currently earns a row. @@ -935,7 +935,7 @@ row. **A change to which options cmdstanr injects does not rebuild anything already built.** An option a later cmdstanr adds can change the artifact while an old -record's `_supplied` goes on matching, and nothing rebuilds. That is the intended +record's `stanc_options` goes on matching, and nothing rebuilds. That is the intended answer: the caller asked for the same build they asked for before, and the new binary is theirs to ask for with `force_recompile = TRUE`. The scheduled case is `--filename-in-msg` (§9), which makes runtime exceptions name the real source rather @@ -946,7 +946,7 @@ models alone. CmdStan is not an exception to that rule. A CmdStan upgrade does rebuild, through -`builder`, because the installation is a standing runtime dependency of the artifact +`cmdstan`, because the installation is a standing runtime dependency of the artifact rather than a fact about how it was built: the binary loads its TBB through an absolute rpath, by default into that tree (§6), and re-resolution invokes that installation's stanc (§6). cmdstanr appears nowhere in the executable. It drives @@ -962,11 +962,11 @@ above rather than an exception to them.** Nothing cmdstanr injects is of that ki and the scheduled addition is not either; `--filename-in-msg` changes which file a runtime exception names. What keeps the class closed is that a correctness fix to generated code belongs to stanc, and a CmdStan upgrade already rebuilds through -`builder`. If a release ever needs one anyway, these are the rules it has to reopen, +`cmdstan`. If a release ever needs one anyway, these are the rules it has to reopen, because a NEWS entry cannot make incorrect reuse safe. Only `stanc_options` has an injected row. With the user header built as a flag -(§3), cmdstanr injects no C++ option at all, so a `cpp_options_injected` would be +(§3), cmdstanr injects no C++ option at all, so a `cpp_options_added` would be empty in every record 1.0 writes. If one ever appears it arrives with the field. **An injection nothing compares still applies.** `--name` is injected too, and its @@ -1209,7 +1209,7 @@ property is testable. **What the reader cannot use, it rejects as unreadable rather than working with.** A file that parses as JSON is not yet a record (§6). Every field the format requires -is checked for type and shape before the record is accepted, `builder`'s version +is checked for type and shape before the record is accepted, `cmdstan`'s version against the grammar §7 defines since a string that is not a CmdStan version is the wrong shape rather than an odd value, and a record failing any of those checks is unreadable whole: nothing in it is used and nothing in it is reported, including a @@ -1361,7 +1361,7 @@ executable was replaced (§2). single-configuration cache lets the most recent compile own the executable and the record beside it, so once another call or process rebuilds, the pair on disk is self-consistent and describes a program this object never saw. The path is -unchanged, the file exists, and the record's `artifact` hash matches the binary it +unchanged, the file exists, and the record's `executable_hash` matches the binary it now sits beside, which is the bond it exists to prove (§4). Nothing on disk disagrees, so the disagreement has to be carried in. For an executable-only object that carried-in hash is the whole check (§7). @@ -1675,7 +1675,7 @@ so this section can be read without holding the table open. Or when the record cannot be used at all: -- the executable does not match `artifact`: replaced by another process, or corrupt +- the executable does not match `executable_hash`: replaced by another process, or corrupt - the record is missing, unreadable, or written in a format version this cmdstanr does not read - the executable predates build records, so there is nothing to compare @@ -1825,7 +1825,7 @@ it does by name: `option -o cannot be repeated` for a `make/local` `-o` beside t it exists so that the build and `stanc --info` resolve the same files, and dropping the flag only when the call also supplies paths would leave the defect in place when it does not. Nothing recorded moves, since the call's options are in -`stanc_options_supplied` and `make/local` is hashed whole. Lands in Stage 1, where +`stanc_options` and `make/local` is hashed whole. Lands in Stage 1, where the boolean repeats already exist; the `--filename-in-msg` injection (§9) relies on it. @@ -1880,7 +1880,7 @@ source is identified by content and its directory is not compared; its basename a compiler input, since `R/model.R:835` passes it to stanc as `--name` and §3 makes the file name the only way to set that flag. So moving a project costs nothing while renaming `bernoulli.stan` to `survival.stan` costs a compile, for the same reason a -changed `stanc_options` entry does. §4's `request.stanc_name` row carries the +changed `stanc_options` entry does. §4's `configuration.stanc_name` row carries the argument. The user header's directory is the exception, for the reason given below. **Path-and-content identity is rejected, and it is the closest call here.** The @@ -1897,7 +1897,7 @@ Correct line, correct column, and whoever moved the project knows where it went. Against that, renaming a working directory from `docs/A` to `docs/B` would pay a full recompile for a benefit its user never receives, and nobody thinks of a directory name as a compiler input. Cross-machine moves almost always rebuild on -`builder` identity anyway, so path identity would be the sole trigger only for the +`cmdstan` identity anyway, so path identity would be the sole trigger only for the folder rename. The rule the rest of this section uses is: rebuild when the artifact would differ in a way the caller can observe and care about. It is why dependencies are hashed rather than trusted by mtime, and why `make/local` rebuilds even on an @@ -1947,7 +1947,7 @@ a lost record costs provenance rather than time. spelling, and nothing beneath it is tracked.** The `-I` flags a user puts in `cpp_options` are the explicit members of that set; the user header's own directory is the implicit one. The two are compared through different fields, the flags as -part of `request.cpp_options_supplied` and the header's path as the one dependency +part of `configuration.cpp_options` and the header's path as the one dependency whose recorded path is compared (§4), but this is one rule with two instances, not a rule plus an exception. @@ -2021,7 +2021,7 @@ refused once (§4). The comparison is the normalised installation path and the version, plus the `make/local` hash, which is its own dependency with its own trigger rather than -part of `builder`. +part of `cmdstan`. @@ -2065,7 +2065,7 @@ because the field is already recorded, and changes no verdict here. the record going bad: the record parses, it hash-binds to this binary, and `stan_build_info()` answers out of it. What it says is that the executable may not run, and whether anything can be done about that turns on the selected installation -rather than the recorded one. Select a different one and `builder` differs, so the +rather than the recorded one. Select a different one and `cmdstan` differs, so the ordinary trigger above has already fired and the model rebuilds against a CmdStan that exists. Leave the selection alone and the gone installation is also the one a rebuild would run in, so making this a trigger buys a doomed compile in place of @@ -2160,7 +2160,7 @@ they were, so that an unresolved set is never read as an empty one. One path reaches it: re-resolution is skipped when the selected -installation differs from `builder` (below). That difference is itself a trigger, +installation differs from `cmdstan` (below). That difference is itself a trigger, so the verdict is the same either way and only the reason list is shorter. @@ -2178,7 +2178,7 @@ against that installation. That is correct: `cmdstan_make_loc `install_cmdstan(overwrite = TRUE)` and the `-fPIC` auto-fix at `R/utils.R:932` all stale those executables, and the last of those fixes a bug for free, since today nothing notices. It is narrower than it first appears: an upgrade installs to a new -directory, so `builder` already differs. +directory, so `cmdstan` already differs. ### Include shadowing is detected, not accepted @@ -2229,10 +2229,10 @@ is free. -**Invoke stanc from the recorded `builder`, not from whichever installation is +**Invoke stanc from the recorded `cmdstan`, not from whichever installation is selected now**, or a different stanc's resolution rules get applied to a model this one did not build. **Check builder identity first**: if the selected installation -differs from `builder`, that is already a rebuild trigger (above) and should be +differs from `cmdstan`, that is already a rebuild trigger (above) and should be reported without attempting re-resolution at all. That leaves one way for the recorded stanc to be missing, the selection being the recorded installation and it being gone, and there the model can be neither assessed nor rebuilt, which is the @@ -2288,7 +2288,7 @@ channel, and not for a `make/local` include, which is not. -**The field is `known_untracked_dependencies`, not `provenance_complete`.** A regex +**The field is `untracked_dependencies`, not `provenance_complete`.** A regex can establish that a gap exists; it cannot establish that none does. Make also has variable expansion and `eval`; C++ has angle-bracket local headers, macro-expanded includes, line continuations and conditional inclusion. **No match means "no known @@ -2468,7 +2468,7 @@ provenance. -`$cpp_options()` returns the recorded `cpp_options_supplied` here, and +`$cpp_options()` returns the recorded `cpp_options` here, and `$user_header()` the recorded header path. That is consistent with §1: the accessor always answers "what was this build asked for", and adoption sources that answer from the record instead of from the current call. Since adoption hydrates from a @@ -2486,7 +2486,7 @@ to learn something the first fit establishes anyway, which is the cost **Executable without a usable record**: missing, unreadable (an unparseable -`builder` version among the field checks that decide it, §4), hash mismatch, or +`cmdstan` version among the field checks that decide it, §4), hash mismatch, or written in a format version this cmdstanr does not read. Explicitly unprovenanced, which is a statement about provenance and must not suppress what the binary does report. `stan_build_info()` returns an explicit unavailable provenance, never an @@ -2512,7 +2512,7 @@ does.** Adoption is the one place a version arrives from an a for; everywhere else it comes from the CmdStan installation the session validated at install time. So this is the only place the invariant §10 relies on can be established. A usable record's half is enforced where the record's other field -checks are (§4), so a record carrying an unparseable `builder` version is not a +checks are (§4), so a record carrying an unparseable `cmdstan` version is not a usable record; on the fallback, ` info` must report complete version fields. Failing both means the executable did not identify itself as a supported CmdStan @@ -2604,7 +2604,7 @@ every call, and cannot be silenced by fixing anything. `stan_build_info()` is ho caller asks. The line is not "standing properties are silent", since §6 does surface -`known_untracked_dependencies` at construction, and should. Nor is it whether the +`untracked_dependencies` at construction, and should. Nor is it whether the user chose the thing: including another makefile from `make/local` is deliberate, and CmdStan's own `make/local.example` ships it as a suggestion (§6). The line is whether the consequence follows from the action. @@ -2949,8 +2949,8 @@ that it returns "a parsed object" does not settle this: the obvious implementati is `jsonlite::fromJSON()` on the record, and then the returned object is the on-disk schema one deserialisation removed. That contradicts §4, which makes the format private and versions it so that it can change. A later cmdstanr that stores -`cpp_options_supplied` in a different shape bumps `format_version` and reshapes the -field, and every script reading `info$request$cpp_options_supplied` breaks on a +`cpp_options` in a different shape bumps `format_version` and reshapes the +field, and every script reading `info$configuration$cpp_options` breaks on a change §4 says is ours to make. So the reader translates: the public field names are the promise, and the record's layout is free underneath them. @@ -2968,13 +2968,13 @@ so §10's note that `stan_build_info()` is still a placeholder covers both. | field | present when | holds | |---|---|---| -| `provenance` | always | `status` and `reason`, both always present | +| `record` | always | `status` and `reason`, both always present | | `reported_features` | always | one entry per feature: four logical flags, each `TRUE`, `FALSE` or `NA`, and `stan_version`, a character scalar or `NA_character_` | | `format_version` | `unsupported_format` only (below) | the format the record was written in | -| `request` | provenance available | the recorded build configuration of §1 | -| `dependencies` | provenance available | every file whose content the build consumed | -| `builder` | provenance available | installation path, version, `exists` | -| `known_untracked_dependencies` | provenance available | §6's list; empty means nothing was detected | +| `configuration` | record available | the recorded build configuration of §1 | +| `dependencies` | record available | every file whose content the build consumed | +| `cmdstan` | record available | installation path, version, `exists` | +| `untracked_dependencies` | record available | §6's list; empty means nothing was detected | @@ -2987,9 +2987,9 @@ shipped yet, so the set can still be chosen freely; after 1.0 it cannot. The has fail that test. The artifact hash answers a question the caller can already answer by hashing the file whose path they just passed in, and the dependency hashes compare against nothing but another record's same field. So do -`stanc_options_injected` and `stanc_name`, which say how cmdstanr assembled the +`stanc_options_added` and `stanc_name`, which say how cmdstanr assembled the stanc command line rather than what was asked of it. `tbb_dir` is out on the same -test; the record keeps it because Windows needs it at launch (§4). `request` keeps +test; the record keeps it because Windows needs it at launch (§4). `configuration` keeps `include_paths` for diagnosis alone: a caller debugging an include has no other way to see where the build searched. @@ -3002,15 +3002,15 @@ that includes another makefile: ```r list( - provenance = list(status = "available", reason = NULL), + record = list(status = "available", reason = NULL), reported_features = list( stan_threads = TRUE, stan_mpi = FALSE, stan_opencl = FALSE, stan_no_range_checks = FALSE, stan_version = "2.39.0" ), - request = list( - cpp_options_supplied = list(STAN_THREADS = TRUE), - stanc_options_supplied = list(), - include_paths = "/proj" + configuration = list( + cpp_options = list(STAN_THREADS = TRUE), + stanc_options = list(), + include_paths = "/proj" ), dependencies = list( stan_file = list(built_from = "/proj/bernoulli.stan", exists = TRUE), @@ -3020,8 +3020,8 @@ list( user_header = NULL, make_local = list(built_from = "/cmdstan-2.39.0/make/local", exists = TRUE) ), - builder = list(path = "/cmdstan-2.39.0", version = "2.39.0", exists = TRUE), - known_untracked_dependencies = list( + cmdstan = list(path = "/cmdstan-2.39.0", version = "2.39.0", exists = TRUE), + untracked_dependencies = list( list(kind = "make_local_include", detected_in = "/cmdstan-2.39.0/make/local") ) ) @@ -3035,7 +3035,7 @@ not the one chosen. **The user header appears once, under `dependencies`.** It is a file the build -read, so it belongs beside the other files the build read rather than in `request` +read, so it belongs beside the other files the build read rather than in `configuration` with the options. §4 compares it as `dependencies.user_header.built_from` and the record holds it in that one place too, so nothing is translated here. The rule exists because carrying it in both is the natural thing to write, and it puts one @@ -3060,7 +3060,7 @@ declines to do, and a field for it would end up holding a path sometimes and a guess the rest of the time. That does repeat a path `dependencies` already holds, which the header rule above -forbids for `request`. The difference is that this field is never compared (§4), so +forbids for `configuration`. The difference is that this field is never compared (§4), so a stale copy cannot move a verdict, and an entry that names its own file is what lets the printer build its message from the entry alone. @@ -3101,22 +3101,22 @@ added here deliberately rather than appearing on its own. -**`provenance` carries why, not only whether.** §7 already enumerates four ways a +**`record` carries why, not only whether.** §7 already enumerates four ways a record fails to describe an executable, and collapsing them to a bare "unavailable" throws the distinction away at the only point a user can act on it: ```r -provenance = list(status = "available", reason = NULL) -provenance = list(status = "unavailable", reason = "record_missing") - # "record_unreadable" - # "artifact_mismatch" - # "unsupported_format" +record = list(status = "available", reason = NULL) +record = list(status = "unavailable", reason = "missing") + # "unreadable" + # "executable_mismatch" + # "unsupported_format" ``` Both names are always there. `available` requires `reason = NULL`, `unavailable` -requires exactly one code, and `names(provenance)` is the same pair either way, +requires exactly one code, and `names(record)` is the same pair either way, which is what a test can hold. The enum is machine-readable and no free-form message is stored. The printer derives its prose from the reason, so the wording stays revisable and never becomes contract. @@ -3128,7 +3128,7 @@ printer's only input: the direction message below is promised behaviour and `print.stan_build_info(x)` receives nothing but `x`, so the version has to reach it through the result. That is a named consumer, and it is what the fields withheld above do not have. The other three reasons carry no version, and -`record_unreadable` is the one to say out loud: an unreadable record is withheld +`unreadable` is the one to say out loud: an unreadable record is withheld whole (§4), so its version goes unreported even where it parsed perfectly well. @@ -3145,11 +3145,11 @@ for an older one. **Unknown and empty must never render alike, anywhere in the result.** This is §6's -`known_untracked_dependencies` rule and §1's absence-of-evidence rule stated once as +`untracked_dependencies` rule and §1's absence-of-evidence rule stated once as a property of the whole object rather than per field. An empty -`known_untracked_dependencies` means the scan detected nothing; no record to scan +`untracked_dependencies` means the scan detected nothing; no record to scan means the field is absent. A recorded builder whose path is gone is -`exists = FALSE`; an absent `builder` means there was no usable record to read one +`exists = FALSE`; an absent `cmdstan` means there was no usable record to read one from, which is the only way it can be missing. An unknown request is absent, not `list()`. @@ -3164,8 +3164,8 @@ unknown. **A readable record whose hash does not match is read only to say why.** -`artifact_mismatch` returns no record-derived field at all, even though `request`, -`dependencies` and `builder` all parsed. `reported_features` still comes back, read +`executable_mismatch` returns no record-derived field at all, even though `configuration`, +`dependencies` and `cmdstan` all parsed. `reported_features` still comes back, read off the executable rather than the record, which is the general rule below and not an exception to this one. This is the one place the reader holds back data it can see. Reporting the fields with a caveat is the natural instinct and it is wrong, @@ -3174,7 +3174,7 @@ validators to. A helpful partial report puts `stan_threads: true` from some othe build in front of a validator guarding this one, which is the silently single-threaded run this design exists to remove, arriving through a new door. Relocation never reaches here: a moved executable keeps its bytes and its hash, and -§6 compares dependencies by content, so `artifact_mismatch` means the executable at +§6 compares dependencies by content, so `executable_mismatch` means the executable at this path was replaced without cmdstanr writing a new record. @@ -3183,7 +3183,7 @@ this path was replaced without cmdstanr writing a new record. reasons are §7's "executable without a usable record", so all four read `reported_features` off the executable; an available one reads them from the record. That is one rule covering five states with nothing carved out of it, and -it is what keeps `artifact_mismatch` narrow: what a mismatched record loses is +it is what keeps `executable_mismatch` narrow: what a mismatched record loses is everything it claims about the build, not what the binary says about itself. A test has to prove where the features came from, not that the field is populated. @@ -3575,7 +3575,7 @@ would not even rebuild. So the recommendation needs a reason that does not depen on the identity rule. **The reason is that registering source hands the rebuild decision to the session, -and `builder` guarantees it fires.** instantiate's defining promise is that models +and `cmdstan` guarantees it fires.** instantiate's defining promise is that models compile at installation and never during use. §6 compares the CmdStan installation path and version, and `install_cmdstan()` puts every version in its own directory, so an upgrade changes both halves: @@ -3792,7 +3792,7 @@ variable, so by the time a record could be written the user's entries and cmdstanr's additions are indistinguishable. Do not fix that with a snapshot taken before line 673; it only works until someone adds a fifth injection site above it. Accumulate injections in their own list and merge the two when converting to -arguments, so `_supplied` and `_injected` are both values the code already holds +arguments, so `stanc_options` and `stanc_options_added` are both values the code already holds and neither is reconstructed. Getting this wrong is silent: it turns every injection into a compared option, and toggling `pedantic` starts recompiling. @@ -3811,7 +3811,7 @@ behaviour, different diagnosis, and the message has to say which happened. **Absence of evidence is not evidence of absence, twice.** `reported_features` is tri-state (§1): a feature CmdStan does not report is unknown, and treating unknown -as disabled reproduces #765 in a new place. `known_untracked_dependencies` (§6) is +as disabled reproduces #765 in a new place. `untracked_dependencies` (§6) is the same shape: an empty list means nothing was detected, never that the record is complete. Check for both rather than trusting the field names. diff --git a/tests/testthat/helper-build-record.R b/tests/testthat/helper-build-record.R index 4e4bc9b61..f752934ca 100644 --- a/tests/testthat/helper-build-record.R +++ b/tests/testthat/helper-build-record.R @@ -9,11 +9,11 @@ local_fake_exe <- function(name = "bernoulli") { example_record <- function(exe_file) { new_build_record( - request = list( - cpp_options_supplied = list(STAN_THREADS = "true"), - stanc_options_supplied = list("--O1"), - stanc_options_injected = list("--name=bernoulli_model"), - stanc_options_inherited = list(), + configuration = list( + cpp_options = list(STAN_THREADS = "true"), + stanc_options = list("--O1"), + stanc_options_added = list("--name=bernoulli_model"), + stanc_options_from_make = list(), stanc_name = "bernoulli", include_paths = list(dirname(exe_file)) ), @@ -29,23 +29,23 @@ example_record <- function(exe_file) { ), make_local = list(hash = "4b5a", built_from = "make/local") ), - artifact = hash_file(exe_file), - builder = list(path = "/opt/cmdstan-2.39.0", version = "2.39.0"), + executable_hash = hash_file(exe_file), + cmdstan = list(path = "/opt/cmdstan-2.39.0", version = "2.39.0"), tbb_dir = "/opt/cmdstan-2.39.0/stan/lib/stan_math/lib/tbb", - known_untracked_dependencies = list( + untracked_dependencies = list( list(kind = "make_local_include", detected_in = "make/local") ) ) } -example_expected <- function(record) { - list(request = record$request, artifact = NULL) +example_wanted <- function(record) { + list(configuration = record$configuration, executable_hash = NULL) } -example_observed <- function(record) { +example_current <- function(record) { list( record = list(status = "available", record = record), dependencies = record$dependencies, - builder = record$builder + cmdstan = record$cmdstan ) } diff --git a/tests/testthat/helper-envvars-and-paths.R b/tests/testthat/helper-envvars-and-paths.R index 763fbcf0b..2d28f8e7b 100644 --- a/tests/testthat/helper-envvars-and-paths.R +++ b/tests/testthat/helper-envvars-and-paths.R @@ -180,8 +180,9 @@ local_cmdstan_make_local <- function(cpp_options, envir = parent.frame(), } # The session's CmdStan version and, on a model object, the version it -# reports. The record beside the executable stays as written, since the -# guard compares it with the installation, not with either cached version. +# reports. The record beside the executable stays as written, since +# assert_current() compares it with the installation, not with either cached +# version. fake_cmdstan_version <- function(version, mod = NULL) { .cmdstanr$VERSION <- version if (!is.null(mod)) { diff --git a/tests/testthat/test-build-assess.R b/tests/testthat/test-build-assess.R index d9383e594..a58291a7e 100644 --- a/tests/testthat/test-build-assess.R +++ b/tests/testthat/test-build-assess.R @@ -1,23 +1,23 @@ test_that("a matching pair is current", { exe <- local_fake_exe() record <- example_record(exe) - expected <- example_expected(record) - observed <- example_observed(record) - expect_equal(assess_build(expected, observed), character(0)) + wanted <- example_wanted(record) + current <- example_current(record) + expect_equal(assess_build(wanted, current), character(0)) }) test_that("every changed row is reported, resolved dependencies included", { exe <- local_fake_exe() record <- example_record(exe) - expected <- example_expected(record) - observed <- example_observed(record) - expected$request$stanc_name <- "other_model" - observed$dependencies$stan_file$hash <- "1e0f" - observed$dependencies$included_files[[1]]$hash <- "3c2d" - observed$dependencies$user_header <- list(hash = "cccc", built_from = "h.hpp") - observed$dependencies$make_local$hash <- "5a4b" + wanted <- example_wanted(record) + current <- example_current(record) + wanted$configuration$stanc_name <- "other_model" + current$dependencies$stan_file$hash <- "1e0f" + current$dependencies$included_files[[1]]$hash <- "3c2d" + current$dependencies$user_header <- list(hash = "cccc", built_from = "h.hpp") + current$dependencies$make_local$hash <- "5a4b" expect_equal( - assess_build(expected, observed), + assess_build(wanted, current), c("stanc_name", "stan_file", "included_files", "user_header", "make_local") ) }) @@ -25,50 +25,50 @@ test_that("every changed row is reported, resolved dependencies included", { test_that("an unusable record is the only reason", { exe <- local_fake_exe() record <- example_record(exe) - expected <- example_expected(record) - observed <- example_observed(record) - expected$request$stanc_name <- "other_model" + wanted <- example_wanted(record) + current <- example_current(record) + wanted$configuration$stanc_name <- "other_model" reasons <- c( - "missing", "unreadable", "unsupported_format", "artifact_mismatch" + "missing", "unreadable", "unsupported_format", "executable_mismatch" ) for (reason in reasons) { - observed$record <- list(status = "unavailable", reason = reason) - expect_equal(assess_build(expected, observed), reason) + current$record <- list(status = "unavailable", reason = reason) + expect_equal(assess_build(wanted, current), reason) } }) test_that("a replaced executable is caught only by the object's own hash", { exe <- local_fake_exe() record <- example_record(exe) - expected <- example_expected(record) - observed <- example_observed(record) - expected$artifact <- "0000" - expect_equal(assess_build(expected, observed), "artifact") - expected$artifact <- NULL - expect_equal(assess_build(expected, observed), character(0)) + wanted <- example_wanted(record) + current <- example_current(record) + wanted$executable_hash <- "0000" + expect_equal(assess_build(wanted, current), "executable") + wanted$executable_hash <- NULL + expect_equal(assess_build(wanted, current), character(0)) }) test_that("unresolved dependencies are skipped, not read as empty", { exe <- local_fake_exe() record <- example_record(exe) - expected <- example_expected(record) - observed <- example_observed(record) - observed$dependencies <- NULL - observed$builder$path <- "/opt/cmdstan-2.40.0" - expect_equal(assess_build(expected, observed), "builder") - expected$request$stanc_name <- "other_model" - expect_equal(assess_build(expected, observed), c("stanc_name", "builder")) + wanted <- example_wanted(record) + current <- example_current(record) + current$dependencies <- NULL + current$cmdstan$path <- "/opt/cmdstan-2.40.0" + expect_equal(assess_build(wanted, current), "cmdstan") + wanted$configuration$stanc_name <- "other_model" + expect_equal(assess_build(wanted, current), c("stanc_name", "cmdstan")) }) -test_that("a gone builder is not a trigger", { +test_that("a gone CmdStan is not a trigger", { exe <- local_fake_exe() record <- example_record(exe) gone <- file.path(withr::local_tempdir(), "cmdstan") expect_false(dir.exists(gone)) - record$builder$path <- gone - expected <- example_expected(record) - observed <- example_observed(record) - expect_equal(assess_build(expected, observed), character(0)) - observed$builder$path <- withr::local_tempdir() - expect_equal(assess_build(expected, observed), "builder") + record$cmdstan$path <- gone + wanted <- example_wanted(record) + current <- example_current(record) + expect_equal(assess_build(wanted, current), character(0)) + current$cmdstan$path <- withr::local_tempdir() + expect_equal(assess_build(wanted, current), "cmdstan") }) diff --git a/tests/testthat/test-build-record-compile.R b/tests/testthat/test-build-record-compile.R index 91726fd2c..eb06098c1 100644 --- a/tests/testthat/test-build-record-compile.R +++ b/tests/testthat/test-build-record-compile.R @@ -29,12 +29,12 @@ test_that("a build writes a record that reads back available", { result <- read_build_record(mod$exe_file()) expect_equal(result$status, "available") - expect_equal(result$record$request$stanc_name, "bernoulli_model") + expect_equal(result$record$configuration$stanc_name, "bernoulli_model") expect_equal( - result$record$builder, + result$record$cmdstan, list(path = cmdstan_path(), version = cmdstan_version()) ) - expect_equal(result$record$artifact, hash_file(mod$exe_file())) + expect_equal(result$record$executable_hash, hash_file(mod$exe_file())) expect_false("user_header" %in% names(result$record$dependencies)) if (!file.exists(file.path(cmdstan_path(), "make", "local"))) { expect_false("make_local" %in% names(result$record$dependencies)) @@ -47,13 +47,14 @@ test_that("the recorded stanc name is the raw string stanc was passed", { mod <- mock_compile(stan_file) record <- read_build_record(mod$exe_file())$record - expect_equal(record$request$stanc_name, "my-model_model") + expect_equal(record$configuration$stanc_name, "my-model_model") expect_true( - "--name=my-model_model" %in% unlist(record$request$stanc_options_injected) + "--name=my-model_model" %in% + unlist(record$configuration$stanc_options_added) ) }) -test_that("supplied and injected stanc options are recorded apart", { +test_that("supplied and added stanc options are recorded apart", { stan_file <- local_bernoulli() mod <- mock_compile( stan_file, @@ -62,9 +63,9 @@ test_that("supplied and injected stanc options are recorded apart", { ) record <- read_build_record(mod$exe_file())$record - expect_equal(record$request$stanc_options_supplied, list("--O1")) + expect_equal(record$configuration$stanc_options, list("--O1")) expect_equal( - record$request$stanc_options_injected, + record$configuration$stanc_options_added, list( "--warn-pedantic", "--name=bernoulli_model", paste0("--filename-in-msg=", wsl_safe_path(mod$stan_file())) @@ -72,7 +73,7 @@ test_that("supplied and injected stanc options are recorded apart", { ) }) -test_that("cpp_options_supplied holds what the caller passed", { +test_that("cpp_options holds what the caller passed", { stan_file <- local_bernoulli() user_header <- withr::local_tempfile(lines = "", fileext = ".hpp") local_mocked_bindings( @@ -85,8 +86,8 @@ test_that("cpp_options_supplied holds what the caller passed", { ) record <- read_build_record(mod$exe_file())$record - expect_equal(record$request$cpp_options_supplied, list(STAN_THREADS = "TRUE")) - expect_false("USER_HEADER" %in% names(record$request$cpp_options_supplied)) + expect_equal(record$configuration$cpp_options, list(STAN_THREADS = "TRUE")) + expect_false("USER_HEADER" %in% names(record$configuration$cpp_options)) expect_equal( record$dependencies$user_header, list(hash = hash_file(user_header), built_from = resolve_path(user_header)) @@ -122,7 +123,7 @@ test_that("included files are recorded in stanc's order with content hashes", { } # The constructor defaults include_paths to the stan file's own directory. expect_equal( - record$request$include_paths, + record$configuration$include_paths, list(resolve_path(dirname(stan_file))) ) }) @@ -153,7 +154,7 @@ test_that("an include on the WSL filesystem is recorded by its share path", { expect_equal(included[[1]]$built_from, resolve_path(include)) }) -test_that("the other injection sites land in the injected list", { +test_that("the other injection sites land in the added list", { user_header <- withr::local_tempfile(lines = "", fileext = ".hpp") local_mocked_bindings( get_standalone_hpp = function(stan_file, stancflags, ...) "" @@ -167,13 +168,13 @@ test_that("the other injection sites land in the injected list", { record <- read_build_record(mod$exe_file())$record expect_equal( - record$request$stanc_options_injected, + record$configuration$stanc_options_added, list( "--use-opencl", "--allow-undefined", "--name=bernoulli_model", paste0("--filename-in-msg=", wsl_safe_path(mod$stan_file())) ) ) - expect_equal(record$request$stanc_options_supplied, list()) + expect_equal(record$configuration$stanc_options, list()) }) test_that("make/local is a dependency only when present", { @@ -260,7 +261,7 @@ test_that("a build with an untracked dependency records it", { record <- read_build_record(mod$exe_file())$record expect_equal( - record$known_untracked_dependencies, + record$untracked_dependencies, list(list(kind = "make_local_include", detected_in = make_local)) ) }) diff --git a/tests/testthat/test-build-record.R b/tests/testthat/test-build-record.R index 97288279b..2c32931d1 100644 --- a/tests/testthat/test-build-record.R +++ b/tests/testthat/test-build-record.R @@ -36,17 +36,17 @@ test_that("a written record reads back unchanged", { test_that("an empty object writes as {} and an empty array as []", { exe <- local_fake_exe() record <- example_record(exe) - record$request$cpp_options_supplied <- structure(list(), names = character()) + record$configuration$cpp_options <- structure(list(), names = character()) record$dependencies$included_files <- list() path <- write_build_record(record, exe) text <- paste(readLines(path, warn = FALSE), collapse = "\n") - expect_match(text, '"cpp_options_supplied"\\s*:\\s*\\{\\s*\\}') + expect_match(text, '"cpp_options"\\s*:\\s*\\{\\s*\\}') expect_match(text, '"included_files"\\s*:\\s*\\[\\s*\\]') result <- read_build_record(exe) expect_equal( - result$record$request$cpp_options_supplied, + result$record$configuration$cpp_options, structure(list(), names = character()) ) expect_equal(result$record$dependencies$included_files, list()) @@ -73,7 +73,7 @@ test_that("a record that is not JSON is unreadable", { test_that("a record with a field of the wrong type is unreadable", { exe <- local_fake_exe() record <- example_record(exe) - record$builder$version <- 42 + record$cmdstan$version <- 42 jsonlite::write_json( record, build_record_path(exe), auto_unbox = TRUE, pretty = TRUE, digits = NA @@ -89,7 +89,7 @@ test_that("a record repeating a member at its top level is unreadable", { exe <- local_fake_exe() json <- jsonlite::toJSON(example_record(exe), auto_unbox = TRUE, digits = NA) writeLines( - sub("}$", ",\"artifact\":\"different\"}", json), + sub("}$", ",\"executable_hash\":\"different\"}", json), build_record_path(exe) ) @@ -133,7 +133,7 @@ test_that("a record in a format we do not read is checked on its version alone", exe <- local_fake_exe() record <- example_record(exe) record$format_version <- 99L - record$builder <- "garbage" + record$cmdstan <- "garbage" jsonlite::write_json( record, build_record_path(exe), auto_unbox = TRUE, pretty = TRUE, digits = NA @@ -166,7 +166,7 @@ test_that("a record whose hash does not match the executable is a mismatch", { writeBin(as.raw(c(0x7f, 0x45, 0x4c, 0x46, 0x00)), exe) result <- read_build_record(exe) - expect_equal(result$reason, "artifact_mismatch") + expect_equal(result$reason, "executable_mismatch") expect_false("record" %in% names(result)) expect_false("format_version" %in% names(result)) }) @@ -210,36 +210,36 @@ test_that("the validator names the field that fails", { rebuild <- function(record) do.call(new_build_record, record[-1]) bad_version <- base - bad_version$builder$version <- "2.39" - expect_error(rebuild(bad_version), "`builder.version`", fixed = TRUE) + bad_version$cmdstan$version <- "2.39" + expect_error(rebuild(bad_version), "`cmdstan.version`", fixed = TRUE) no_name <- base - no_name$request$stanc_name <- "" - expect_error(rebuild(no_name), "`request.stanc_name`", fixed = TRUE) + no_name$configuration$stanc_name <- "" + expect_error(rebuild(no_name), "`configuration.stanc_name`", fixed = TRUE) logical_option <- base - logical_option$request$cpp_options_supplied <- list(STAN_THREADS = TRUE) + logical_option$configuration$cpp_options <- list(STAN_THREADS = TRUE) expect_error( rebuild(logical_option), - "`request.cpp_options_supplied.STAN_THREADS`", + "`configuration.cpp_options.STAN_THREADS`", fixed = TRUE ) repeated_option <- base - repeated_option$request$cpp_options_supplied <- list( + repeated_option$configuration$cpp_options <- list( STAN_THREADS = "false", STAN_THREADS = "true" ) expect_error( - rebuild(repeated_option), "`request.cpp_options_supplied`", fixed = TRUE + rebuild(repeated_option), "`configuration.cpp_options`", fixed = TRUE ) unknown_kind <- base - unknown_kind$known_untracked_dependencies <- list( + unknown_kind$untracked_dependencies <- list( list(kind = "mystery", detected_in = "make/local") ) expect_error( rebuild(unknown_kind), - "`known_untracked_dependencies[[1]].kind`", + "`untracked_dependencies[[1]].kind`", fixed = TRUE ) @@ -298,8 +298,8 @@ test_that("the hash catches what ordering cannot", { write_build_record(record_b, path) write_build_record(record_a, path) - expect_error(verify_build_record(path), "artifact_mismatch", fixed = TRUE) - expect_equal(read_build_record(path)$reason, "artifact_mismatch") + expect_error(verify_build_record(path), "executable_mismatch", fixed = TRUE) + expect_equal(read_build_record(path)$reason, "executable_mismatch") }) test_that("two identical build records compare with no differences", { @@ -313,16 +313,16 @@ test_that("a changed cpp option value differs as cpp_options", { exe <- local_fake_exe() recorded <- example_record(exe) current <- example_record(exe) - current$request$cpp_options_supplied <- list(STAN_THREADS = "false") + current$configuration$cpp_options <- list(STAN_THREADS = "false") expect_equal(compare_build_records(recorded, current), "cpp_options") }) -test_that("a reordered stanc_options_supplied differs as stanc_options", { +test_that("a reordered stanc_options differs as stanc_options", { exe <- local_fake_exe() recorded <- example_record(exe) current <- example_record(exe) - recorded$request$stanc_options_supplied <- list("--O0", "--O1") - current$request$stanc_options_supplied <- list("--O1", "--O0") + recorded$configuration$stanc_options <- list("--O0", "--O1") + current$configuration$stanc_options <- list("--O1", "--O0") expect_equal(compare_build_records(recorded, current), "stanc_options") }) @@ -330,8 +330,8 @@ test_that("a changed stanc option differs as stanc_options", { exe <- local_fake_exe() recorded <- example_record(exe) current <- example_record(exe) - recorded$request$stanc_options_supplied <- list("--O0") - current$request$stanc_options_supplied <- list("--O1") + recorded$configuration$stanc_options <- list("--O0") + current$configuration$stanc_options <- list("--O1") expect_equal(compare_build_records(recorded, current), "stanc_options") }) @@ -339,7 +339,7 @@ test_that("a changed stanc_name differs as stanc_name", { exe <- local_fake_exe() recorded <- example_record(exe) current <- example_record(exe) - current$request$stanc_name <- "other_model" + current$configuration$stanc_name <- "other_model" expect_equal(compare_build_records(recorded, current), "stanc_name") }) @@ -347,8 +347,8 @@ test_that("a rename stanc mangles to the same identifier still differs as stanc_ exe <- local_fake_exe() recorded <- example_record(exe) current <- example_record(exe) - recorded$request$stanc_name <- "my-model_model" - current$request$stanc_name <- "my_model_model" + recorded$configuration$stanc_name <- "my-model_model" + current$configuration$stanc_name <- "my_model_model" expect_equal(compare_build_records(recorded, current), "stanc_name") }) @@ -417,28 +417,28 @@ test_that("a changed make_local hash differs as make_local", { expect_equal(compare_build_records(recorded, current), "make_local") }) -test_that("a changed artifact differs as artifact", { +test_that("a changed executable hash differs as executable", { exe <- local_fake_exe() recorded <- example_record(exe) current <- example_record(exe) - current$artifact <- "deadbeef" - expect_equal(compare_build_records(recorded, current), "artifact") + current$executable_hash <- "deadbeef" + expect_equal(compare_build_records(recorded, current), "executable") }) -test_that("a changed builder version differs as builder", { +test_that("a changed cmdstan version differs as cmdstan", { exe <- local_fake_exe() recorded <- example_record(exe) current <- example_record(exe) - current$builder$version <- "2.40.0" - expect_equal(compare_build_records(recorded, current), "builder") + current$cmdstan$version <- "2.40.0" + expect_equal(compare_build_records(recorded, current), "cmdstan") }) -test_that("a changed builder path differs as builder", { +test_that("a changed cmdstan path differs as cmdstan", { exe <- local_fake_exe() recorded <- example_record(exe) current <- example_record(exe) - current$builder$path <- "/opt/cmdstan-2.40.0" - expect_equal(compare_build_records(recorded, current), "builder") + current$cmdstan$path <- "/opt/cmdstan-2.40.0" + expect_equal(compare_build_records(recorded, current), "cmdstan") }) test_that("two differences are both reported, in table order", { @@ -446,18 +446,18 @@ test_that("two differences are both reported, in table order", { recorded <- example_record(exe) current <- example_record(exe) current$dependencies$stan_file$hash <- "ffff" - current$builder$version <- "2.40.0" - expect_equal(compare_build_records(recorded, current), c("stan_file", "builder")) + current$cmdstan$version <- "2.40.0" + expect_equal(compare_build_records(recorded, current), c("stan_file", "cmdstan")) }) test_that("the same cpp options in a different assignment order do not differ", { exe <- local_fake_exe() recorded <- example_record(exe) current <- example_record(exe) - recorded$request$cpp_options_supplied <- list( + recorded$configuration$cpp_options <- list( STAN_THREADS = "true", STAN_NO_RANGE_CHECKS = "true" ) - current$request$cpp_options_supplied <- list( + current$configuration$cpp_options <- list( STAN_NO_RANGE_CHECKS = "true", STAN_THREADS = "true" ) expect_equal(compare_build_records(recorded, current), character(0)) @@ -489,22 +489,22 @@ test_that("differences outside the comparison table never count", { exe <- local_fake_exe() recorded <- example_record(exe) current <- example_record(exe) - current$request$stanc_options_injected <- list("--name=other_model") - current$request$include_paths <- list("/some/other/path") + current$configuration$stanc_options_added <- list("--name=other_model") + current$configuration$include_paths <- list("/some/other/path") current$reported_features$stan_opencl <- TRUE current$tbb_dir <- "/opt/other/tbb" - current$known_untracked_dependencies <- list( + current$untracked_dependencies <- list( list(kind = "user_header_include", detected_in = "other.hpp") ) expect_equal(compare_build_records(recorded, current), character(0)) }) -test_that("an injection added after the build does not rebuild", { +test_that("an option added after the build does not rebuild", { exe <- local_fake_exe() recorded <- example_record(exe) current <- example_record(exe) - current$request$stanc_options_injected <- c( - recorded$request$stanc_options_injected, + current$configuration$stanc_options_added <- c( + recorded$configuration$stanc_options_added, list("--filename-in-msg=/home/me/bernoulli.stan") ) expect_equal(compare_build_records(recorded, current), character(0)) diff --git a/tests/testthat/test-model-guard.R b/tests/testthat/test-model-guard.R index e63ccb5a1..2c336d669 100644 --- a/tests/testthat/test-model-guard.R +++ b/tests/testthat/test-model-guard.R @@ -4,12 +4,12 @@ set_cmdstan_path() # public member: whether it checks that the executable is still the one the # object was built against before it does anything else. member_class <- c( - sample = "guarded", sample_mpi = "guarded", optimize = "guarded", - laplace = "guarded", variational = "guarded", pathfinder = "guarded", - generate_quantities = "guarded", diagnose = "guarded", - cmdstan_defaults = "guarded", expose_functions = "guarded", - code = "snapshot", variables = "snapshot", print = "snapshot", - hpp_file = "snapshot", save_hpp_file = "snapshot", functions = "snapshot", + sample = "checked", sample_mpi = "checked", optimize = "checked", + laplace = "checked", variational = "checked", pathfinder = "checked", + generate_quantities = "checked", diagnose = "checked", + cmdstan_defaults = "checked", expose_functions = "checked", + code = "stored", variables = "stored", print = "stored", + hpp_file = "stored", save_hpp_file = "stored", functions = "stored", stan_file = "accessor", has_stan_file = "accessor", model_name = "accessor", exe_file = "accessor", include_paths = "accessor", cmdstan_version = "accessor", cpp_options = "accessor", @@ -53,23 +53,23 @@ test_that("every public member is classified, and only those", { expect_false("compile" %in% names(member_class)) }) -test_that("every guarded member raises the staleness error, bare", { +test_that("every checked method raises the staleness error, bare", { mod <- local_stale_model() - guarded <- names(member_class)[member_class == "guarded"] - for (name in guarded) { + checked <- names(member_class)[member_class == "checked"] + for (name in checked) { expect_error( mod[[name]](), class = "cmdstanr_stale_executable", info = name ) } }) -test_that("every non-guarded member gets past the guard", { +test_that("every method that is not checked works on a stale build", { mod <- local_stale_model() - non_guarded <- setdiff( - names(member_class)[member_class != "guarded"], + unchecked <- setdiff( + names(member_class)[member_class != "checked"], c("initialize", "clone", "functions", "print") ) - for (name in non_guarded) { + for (name in unchecked) { expect_true(not_stale(mod[[name]]()), info = name) } capture.output(expect_true(not_stale(mod$print()))) @@ -77,20 +77,20 @@ test_that("every non-guarded member gets past the guard", { expect_true(is.environment(mod$functions)) }) -test_that("the guard says what is stale and where to go", { +test_that("assert_current() says what is stale and where to go", { mod <- local_stale_model() expect_error(mod$sample(), "the Stan program changed", fixed = TRUE) expect_error(mod$sample(), "Run cmdstan_model() to rebuild it.", fixed = TRUE) }) -test_that("the guard is not memoised", { +test_that("assert_current() is not memoised", { mod <- local_stale_model() code <- readLines(mod$stan_file()) writeLines(code[-length(code)], mod$stan_file()) expect_true(not_stale(mod$cmdstan_defaults())) }) -test_that("a current model gets past the guard", { +test_that("a current model passes assert_current()", { stan_file <- write_stan_file( "parameters { real y; } model { y ~ std_normal(); }", dir = withr::local_tempdir() @@ -99,7 +99,7 @@ test_that("a current model gets past the guard", { expect_true(not_stale(mod$cmdstan_defaults())) }) -test_that("the guard names an altered or missing executable", { +test_that("assert_current() names an altered or missing executable", { stan_file <- write_stan_file( "parameters { real y; } model { y ~ std_normal(); }", dir = withr::local_tempdir() diff --git a/tests/testthat/test-model-rebuild-rules.R b/tests/testthat/test-model-rebuild-rules.R index b656f0383..48c18b306 100644 --- a/tests/testthat/test-model-rebuild-rules.R +++ b/tests/testthat/test-model-rebuild-rules.R @@ -104,7 +104,7 @@ test_that("stanc_options rebuild when they change, and pedantic never does", { cmdstan_model(stan_file, stanc_options = list("O1")) )) - # --warn-pedantic is injected rather than supplied, so it is not compared. + # --warn-pedantic is added rather than supplied, so it is not compared. mocked(expect_no_mock_compile( cmdstan_model(stan_file, stanc_options = list("O1"), pedantic = TRUE) )) @@ -247,9 +247,9 @@ test_that("a record naming another installation rebuilds", { mocked(expect_mock_compile(mod <- cmdstan_model(stan_file))) # The executable is untouched, so its hash still matches the record and the - # builder is the only row that differs. + # cmdstan is the only row that differs. record <- read_build_record(mod$exe_file())$record - record$builder$version <- "1.2.3" + record$cmdstan$version <- "1.2.3" write_build_record(record, mod$exe_file()) mocked(expect_mock_compile(expect_interactive_message( @@ -280,7 +280,8 @@ test_that("a CmdStan rebuilt in place at a newer version is a rebuild reason", { a <- mock_cmdstan_model(stan_file) writeLines("CMDSTAN_VERSION := 2.40.0", file.path(install_dir, "makefile")) - # The guard first, while the executable is still the one a was built with + # assert_current() first, while the executable is still the one a was + # built with expect_error( a$cmdstan_defaults(), "the selected CmdStan changed", class = "cmdstanr_stale_executable" @@ -377,7 +378,9 @@ test_that("an unusable record falls back to asking the executable", { writeLines("{", record_path) expect_asked() for (broken in list( - list(format_version = 99L), list(artifact = "wrong"), list(builder = "x") + list(format_version = 99L), + list(executable_hash = "wrong"), + list(cmdstan = "x") )) { record <- original record[names(broken)] <- broken @@ -417,7 +420,7 @@ test_that("a record member with a longer name is not read as the user header", { expect_null(b$user_header()) }) -test_that("filename-in-msg supplied unnamed is not injected again", { +test_that("filename-in-msg supplied unnamed is not added again", { stan_file <- local_bernoulli() mod <- mock_cmdstan_model( stan_file, stanc_options = list("filename-in-msg=published.stan") @@ -426,10 +429,10 @@ test_that("filename-in-msg supplied unnamed is not injected again", { record <- read_build_record(mod$exe_file())$record expect_true( "--filename-in-msg=published.stan" %in% - unlist(record$request$stanc_options_supplied) + unlist(record$configuration$stanc_options) ) expect_false(any(grepl( - "filename-in-msg", unlist(record$request$stanc_options_injected) + "filename-in-msg", unlist(record$configuration$stanc_options_added) ))) hpp <- paste(readLines(mod$hpp_file()), collapse = "\n") expect_match(hpp, "published.stan", fixed = TRUE) diff --git a/tests/testthat/test-model-rebuild.R b/tests/testthat/test-model-rebuild.R index 0e11192a4..fb9965efe 100644 --- a/tests/testthat/test-model-rebuild.R +++ b/tests/testthat/test-model-rebuild.R @@ -60,7 +60,7 @@ mod_b <- cmdstan_model(replaced_stan_file, force_recompile = TRUE) test_that("a replaced executable is refused by the object that built it", { expect_error( mod_a$cmdstan_defaults(), - "replaced after this model was created", fixed = TRUE, + "changed after this model was created", fixed = TRUE, class = "cmdstanr_stale_executable" ) expect_no_error(mod_b$cmdstan_defaults()) @@ -76,7 +76,7 @@ test_that("adoption from a record verifies by hash alone", { cmdstan_model(replaced_stan_file, force_recompile = TRUE) expect_error( mod_c$cmdstan_defaults(), - "replaced after this model was created", fixed = TRUE, + "changed after this model was created", fixed = TRUE, class = "cmdstanr_stale_executable" ) }) @@ -111,7 +111,7 @@ test_that("adoption without a record verifies by the hash it captured", { file.copy(bernoulli_exe, exe, overwrite = TRUE) expect_error( mod_d$cmdstan_defaults(), - "replaced after this model was created", fixed = TRUE, + "changed after this model was created", fixed = TRUE, class = "cmdstanr_stale_executable" ) }) @@ -141,7 +141,7 @@ test_that("an edited program with an old mtime still triggers a rebuild", { expect_error(mod$cmdstan_defaults(), class = "cmdstanr_stale_executable") }) -test_that("a re-resolution failure errors instead of producing a verdict", { +test_that("a failure resolving again errors instead of producing a verdict", { dir <- withr::local_tempdir() stan_file <- seed_from(canonical_include_stan, canonical_include_exe, dir) mod <- cmdstan_model(stan_file) @@ -160,7 +160,7 @@ test_that("a re-resolution failure errors instead of producing a verdict", { test_that("adoption from a record ignores a CmdStan it never selected", { record <- read_build_record(mod_b$exe_file())$record - record$builder$version <- "2.35.0" + record$cmdstan$version <- "2.35.0" write_build_record(record, mod_b$exe_file()) mod <- with_mocked_cli( @@ -379,16 +379,16 @@ test_that("log_prob after an edit still reflects the program that was built", { expect_equal(fit$log_prob(unconstrained_variables = 0.3), expected_lp) }) -test_that("a make/local pedantic flag is injected once, not inherited too", { +test_that("a pedantic flag both added and in make/local is recorded once, as added", { local_cmdstan_make_local(cpp_options = list("STANCFLAGS += --warn-pedantic")) stan_file <- local_program("bernoulli") mod <- mock_cmdstan_model(stan_file, pedantic = TRUE) record <- read_build_record(mod$exe_file())$record - injected <- unlist(record$request$stanc_options_injected) - inherited <- unlist(record$request$stanc_options_inherited) - expect_equal(sum(injected == "--warn-pedantic"), 1) - expect_false("--warn-pedantic" %in% inherited) + added <- unlist(record$configuration$stanc_options_added) + from_make <- unlist(record$configuration$stanc_options_from_make) + expect_equal(sum(added == "--warn-pedantic"), 1) + expect_false("--warn-pedantic" %in% from_make) expect_true(file.exists(mod$hpp_file())) }) diff --git a/tests/testthat/test-utils.R b/tests/testthat/test-utils.R index cc341d7f9..ca04c30c9 100644 --- a/tests/testthat/test-utils.R +++ b/tests/testthat/test-utils.R @@ -465,11 +465,11 @@ test_that("install_executable() restores both files if the pair fails verificati fixture <- local_exe_fixture() # A record that describes some other executable still writes, so only the # verification at the end of the transaction can catch it. - fixture$record$artifact <- "deadbeef" + fixture$record$executable_hash <- "deadbeef" expect_error( install_executable(fixture$from, fixture$to, fixture$record), - "artifact_mismatch", + "executable_mismatch", fixed = TRUE ) expect_identical(readLines(fixture$to), "old executable")