Push checkmate through load

This commit is contained in:
Ayaz Hafiz 2023-07-16 14:47:05 -05:00
parent 27dd9d03aa
commit 1282110ef5
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
14 changed files with 167 additions and 45 deletions

View file

@ -3,6 +3,7 @@ use roc_types::subs as s;
use crate::convert::AsSchema;
#[derive(Debug)]
pub struct Collector {
events: AllEvents,
current_event_path: Vec<usize>,

View file

@ -29,7 +29,7 @@ macro_rules! debug_checkmate {
#[macro_export]
macro_rules! with_checkmate {
($opt_collector:expr, { on => $on:expr, off => $off:expr, }) => {{
({ on => $on:expr, off => $off:expr, }) => {{
#[cfg(debug_assertions)]
{
$on

View file

@ -3,7 +3,7 @@ use std::collections::HashMap;
use schemars::{schema::RootSchema, schema_for, JsonSchema};
use serde::Serialize;
#[derive(Serialize, JsonSchema)]
#[derive(Serialize, JsonSchema, Debug)]
#[serde(tag = "type")]
pub enum Constraint {}
@ -12,7 +12,7 @@ pub struct Variable(pub u32);
macro_rules! impl_content {
($($name:ident { $($arg:ident: $ty:ty,)* },)*) => {
#[derive(Serialize, JsonSchema)]
#[derive(Serialize, JsonSchema, Debug)]
#[serde(tag = "type")]
pub enum Content {
$(
@ -104,40 +104,40 @@ impl_content! {
Error {},
}
#[derive(Serialize, JsonSchema)]
#[derive(Serialize, JsonSchema, Debug)]
pub struct ClosureType {
pub function: Symbol,
pub environment: Vec<Variable>,
}
#[derive(Serialize, JsonSchema)]
#[derive(Serialize, JsonSchema, Debug)]
pub struct UnspecializedClosureType {
pub specialization: Variable,
pub ability_member: Symbol,
pub lambda_set_region: u8,
}
#[derive(Serialize, JsonSchema)]
#[derive(Serialize, JsonSchema, Debug)]
#[serde(tag = "type")]
pub enum AliasKind {
Structural,
Opaque,
}
#[derive(Serialize, JsonSchema)]
#[derive(Serialize, JsonSchema, Debug)]
pub struct AliasTypeVariables {
pub type_variables: Vec<Variable>,
pub lambda_set_variables: Vec<Variable>,
pub infer_ext_in_output_position_variables: Vec<Variable>,
}
#[derive(Serialize, JsonSchema)]
#[derive(Serialize, JsonSchema, Debug)]
pub struct RecordField {
pub kind: RecordFieldKind,
pub field_type: Variable,
}
#[derive(Serialize, JsonSchema)]
#[derive(Serialize, JsonSchema, Debug)]
#[serde(tag = "type")]
pub enum RecordFieldKind {
Demanded,
@ -145,43 +145,43 @@ pub enum RecordFieldKind {
Optional { rigid: bool },
}
#[derive(Serialize, JsonSchema)]
#[derive(Serialize, JsonSchema, Debug)]
#[serde(tag = "type")]
pub enum TagUnionExtension {
Openness(Variable),
Any(Variable),
}
#[derive(Serialize, JsonSchema)]
#[derive(Serialize, JsonSchema, Debug)]
pub struct NumericRange {
pub kind: NumericRangeKind,
pub signed: bool,
pub min_width: u32,
}
#[derive(Serialize, JsonSchema)]
#[derive(Serialize, JsonSchema, Debug)]
#[serde(tag = "type")]
pub enum NumericRangeKind {
Int,
AnyNum,
}
#[derive(Serialize, JsonSchema)]
#[derive(Serialize, JsonSchema, Debug)]
pub struct Rank(pub u32);
#[derive(Serialize, JsonSchema)]
#[derive(Serialize, JsonSchema, Debug)]
pub struct Descriptor {
pub content: Content,
pub rank: Rank,
}
#[derive(Serialize, JsonSchema)]
#[derive(Serialize, JsonSchema, Debug)]
pub struct Symbol(
// TODO: should this be module ID + symbol?
pub String,
);
#[derive(Serialize, JsonSchema)]
#[derive(Serialize, JsonSchema, Debug)]
#[serde(tag = "type")]
pub enum UnificationMode {
Eq,
@ -189,7 +189,7 @@ pub enum UnificationMode {
LambdaSetSpecialization,
}
#[derive(Serialize, JsonSchema)]
#[derive(Serialize, JsonSchema, Debug)]
#[serde(tag = "type")]
pub enum Event {
VariableEvent(VariableEvent),
@ -202,10 +202,10 @@ pub enum Event {
},
}
#[derive(Serialize, JsonSchema)]
#[derive(Serialize, JsonSchema, Debug)]
pub struct AllEvents(pub Vec<Event>);
#[derive(Serialize, JsonSchema)]
#[derive(Serialize, JsonSchema, Debug)]
#[serde(tag = "type")]
pub enum VariableEvent {
Unify {

View file

@ -80,7 +80,7 @@ impl Env<'_> {
let unified = unify(
// TODO(checkmate): pass checkmate through
&mut with_checkmate!(None, {
&mut with_checkmate!({
on => Env::new(self.subs, None),
off => Env::new(self.subs),
}),
@ -121,7 +121,7 @@ impl Env<'_> {
let unified = unify_introduced_ability_specialization(
// TODO(checkmate): pass checkmate through
&mut with_checkmate!(None, {
&mut with_checkmate!({
on => Env::new(self.subs, None),
off => Env::new(self.subs),
}),

View file

@ -364,7 +364,7 @@ pub fn unify(
);
let unified = roc_unify::unify::unify_with_collector::<ChangedVariableCollector>(
// TODO(checkmate): pass checkmate through
&mut with_checkmate!(None, {
&mut with_checkmate!({
on => UEnv::new(subs, None),
off => UEnv::new(subs),
}),
@ -395,6 +395,9 @@ pub fn unify(
derived_env: &derived_env,
arena,
pools: &mut pools,
#[cfg(debug_assertions)]
checkmate: None,
};
compact_lambda_sets_of_vars(&mut env, lambda_sets_to_specialize, &late_phase)

View file

@ -10,6 +10,7 @@ version.workspace = true
[dependencies]
roc_builtins = { path = "../builtins" }
roc_can = { path = "../can" }
roc_checkmate = { path = "../checkmate" }
roc_collections = { path = "../collections" }
roc_constrain = { path = "../constrain" }
roc_debug_flags = { path = "../debug_flags" }

View file

@ -331,6 +331,13 @@ fn start_phase<'a>(
let derived_module = SharedDerivedModule::clone(&state.derived_module);
#[cfg(debug_assertions)]
let checkmate = if roc_checkmate::is_checkmate_enabled() {
Some(roc_checkmate::Collector::new())
} else {
None
};
BuildTask::solve_module(
module,
ident_ids,
@ -347,6 +354,9 @@ fn start_phase<'a>(
declarations,
state.cached_types.clone(),
derived_module,
//
#[cfg(debug_assertions)]
checkmate,
)
}
Phase::FindSpecializations => {
@ -361,6 +371,9 @@ fn start_phase<'a>(
ident_ids,
abilities_store,
expectations,
//
#[cfg(debug_assertions)]
checkmate: _,
} = typechecked;
let mut imported_module_thunks = bumpalo::collections::Vec::new_in(arena);
@ -567,6 +580,9 @@ enum Msg<'a> {
abilities_store: AbilitiesStore,
loc_expects: LocExpects,
loc_dbgs: LocDbgs,
#[cfg(debug_assertions)]
checkmate: Option<roc_checkmate::Collector>,
},
FinishedAllTypeChecking {
solved_subs: Solved<Subs>,
@ -577,6 +593,9 @@ enum Msg<'a> {
dep_idents: IdentIdsByModule,
documentation: VecMap<ModuleId, ModuleDocumentation>,
abilities_store: AbilitiesStore,
#[cfg(debug_assertions)]
checkmate: Option<roc_checkmate::Collector>,
},
FoundSpecializations {
module_id: ModuleId,
@ -878,6 +897,9 @@ enum BuildTask<'a> {
dep_idents: IdentIdsByModule,
cached_subs: CachedTypeState,
derived_module: SharedDerivedModule,
#[cfg(debug_assertions)]
checkmate: Option<roc_checkmate::Collector>,
},
BuildPendingSpecializations {
module_timing: ModuleTiming,
@ -1393,6 +1415,9 @@ fn state_thread_step<'a>(
dep_idents,
documentation,
abilities_store,
#[cfg(debug_assertions)]
checkmate,
} => {
// We're done! There should be no more messages pending.
debug_assert!(msg_rx.is_empty());
@ -1412,6 +1437,9 @@ fn state_thread_step<'a>(
dep_idents,
documentation,
abilities_store,
//
#[cfg(debug_assertions)]
checkmate,
);
Ok(ControlFlow::Break(LoadResult::TypeChecked(typechecked)))
@ -2387,6 +2415,7 @@ fn update<'a>(
abilities_store,
loc_expects,
loc_dbgs,
checkmate,
} => {
log!("solved types for {:?}", module_id);
module_timing.end_time = Instant::now();
@ -2496,6 +2525,9 @@ fn update<'a>(
dep_idents,
documentation,
abilities_store,
#[cfg(debug_assertions)]
checkmate,
})
.map_err(|_| LoadingProblem::MsgChannelDied)?;
@ -2529,6 +2561,9 @@ fn update<'a>(
ident_ids,
abilities_store,
expectations: opt_expectations,
#[cfg(debug_assertions)]
checkmate,
};
state
@ -3176,6 +3211,8 @@ fn finish(
dep_idents: IdentIdsByModule,
documentation: VecMap<ModuleId, ModuleDocumentation>,
abilities_store: AbilitiesStore,
//
#[cfg(debug_assertions)] checkmate: Option<roc_checkmate::Collector>,
) -> LoadedModule {
let module_ids = Arc::try_unwrap(state.arc_modules)
.unwrap_or_else(|_| panic!("There were still outstanding Arc references to module_ids"))
@ -3224,6 +3261,9 @@ fn finish(
timings: state.timings,
docs_by_module: documentation,
abilities_store,
#[cfg(debug_assertions)]
checkmate,
}
}
@ -4441,6 +4481,8 @@ impl<'a> BuildTask<'a> {
declarations: Declarations,
cached_subs: CachedTypeState,
derived_module: SharedDerivedModule,
#[cfg(debug_assertions)] checkmate: Option<roc_checkmate::Collector>,
) -> Self {
let exposed_by_module = exposed_types.retain_modules(imported_modules.keys());
@ -4463,6 +4505,9 @@ impl<'a> BuildTask<'a> {
module_timing,
cached_subs,
derived_module,
#[cfg(debug_assertions)]
checkmate,
}
}
}
@ -4718,6 +4763,9 @@ struct SolveResult {
exposed_vars_by_symbol: Vec<(Symbol, Variable)>,
problems: Vec<TypeError>,
abilities_store: AbilitiesStore,
#[cfg(debug_assertions)]
checkmate: Option<roc_checkmate::Collector>,
}
#[allow(clippy::complexity)]
@ -4731,6 +4779,8 @@ fn run_solve_solve(
var_store: VarStore,
module: Module,
derived_module: SharedDerivedModule,
#[cfg(debug_assertions)] checkmate: Option<roc_checkmate::Collector>,
) -> SolveResult {
let Module {
exposed_symbols,
@ -4782,6 +4832,8 @@ fn run_solve_solve(
pending_derives,
exposed_by_module: &exposed_for_module.exposed_by_module,
derived_module,
#[cfg(debug_assertions)]
checkmate,
};
let solve_output = roc_solve::module::run_solve(
@ -4824,6 +4876,9 @@ fn run_solve_solve(
scope: _,
errors,
resolved_abilities_store,
#[cfg(debug_assertions)]
checkmate,
} = solve_output;
SolveResult {
@ -4832,6 +4887,9 @@ fn run_solve_solve(
exposed_vars_by_symbol,
problems: errors,
abilities_store: resolved_abilities_store,
#[cfg(debug_assertions)]
checkmate,
}
}
@ -4850,6 +4908,8 @@ fn run_solve<'a>(
dep_idents: IdentIdsByModule,
cached_types: CachedTypeState,
derived_module: SharedDerivedModule,
#[cfg(debug_assertions)] checkmate: Option<roc_checkmate::Collector>,
) -> Msg<'a> {
let solve_start = Instant::now();
@ -4876,6 +4936,9 @@ fn run_solve<'a>(
var_store,
module,
derived_module,
//
#[cfg(debug_assertions)]
checkmate,
),
Some(TypeState {
subs,
@ -4888,6 +4951,9 @@ fn run_solve<'a>(
exposed_vars_by_symbol,
problems: vec![],
abilities_store: abilities,
#[cfg(debug_assertions)]
checkmate: None,
},
}
} else {
@ -4901,6 +4967,9 @@ fn run_solve<'a>(
var_store,
module,
derived_module,
//
#[cfg(debug_assertions)]
checkmate,
)
}
};
@ -4911,6 +4980,9 @@ fn run_solve<'a>(
exposed_vars_by_symbol,
problems,
abilities_store,
#[cfg(debug_assertions)]
checkmate,
} = solve_result;
let exposed_types = roc_solve::module::exposed_types_storage_subs(
@ -4945,6 +5017,9 @@ fn run_solve<'a>(
abilities_store,
loc_expects,
loc_dbgs,
#[cfg(debug_assertions)]
checkmate,
}
}
@ -6160,6 +6235,9 @@ fn run_task<'a>(
dep_idents,
cached_subs,
derived_module,
#[cfg(debug_assertions)]
checkmate,
} => Ok(run_solve(
module,
ident_ids,
@ -6175,6 +6253,9 @@ fn run_task<'a>(
dep_idents,
cached_subs,
derived_module,
//
#[cfg(debug_assertions)]
checkmate,
)),
BuildPendingSpecializations {
module_id,

View file

@ -46,6 +46,9 @@ pub struct LoadedModule {
pub timings: MutMap<ModuleId, ModuleTiming>,
pub docs_by_module: VecMap<ModuleId, ModuleDocumentation>,
pub abilities_store: AbilitiesStore,
#[cfg(debug_assertions)]
pub checkmate: Option<roc_checkmate::Collector>,
}
impl LoadedModule {
@ -125,6 +128,9 @@ pub struct TypeCheckedModule<'a> {
pub ident_ids: IdentIds,
pub abilities_store: AbilitiesStore,
pub expectations: Option<Expectations>,
#[cfg(debug_assertions)]
pub checkmate: Option<roc_checkmate::Collector>,
}
#[derive(Debug)]

View file

@ -1294,7 +1294,7 @@ impl DerivableVisitor for DeriveEq {
// only Dec implements Eq.
// TODO(checkmate): pass checkmate through
let unified = unify(
&mut with_checkmate!(None, {
&mut with_checkmate!({
on => UEnv::new(subs, None),
off => UEnv::new(subs),
}),
@ -1430,7 +1430,7 @@ pub fn resolve_ability_specialization<R: AbilityResolver>(
instantiate_rigids(subs, signature_var);
let (_vars, must_implement_ability, _lambda_sets_to_specialize, _meta) = unify(
// TODO(checkmate): pass checkmate through
&mut with_checkmate!(None, {
&mut with_checkmate!({
on => UEnv::new(subs, None),
off => UEnv::new(subs),
}),

View file

@ -19,6 +19,8 @@ pub struct SolveEnv<'a> {
pub derived_env: &'a DerivedEnv<'a>,
pub subs: &'a mut Subs,
pub pools: &'a mut Pools,
#[cfg(debug_assertions)]
pub checkmate: Option<roc_checkmate::Collector>,
}
/// Environment necessary for inference.
@ -94,9 +96,8 @@ impl<'a> InferenceEnv<'a> {
/// Retrieves an environment for unification.
pub fn uenv(&mut self) -> UEnv {
// TODO(checkmate): pass checkmate through
with_checkmate!(None, {
on => UEnv::new(self.subs, None),
with_checkmate!({
on => UEnv::new(self.subs, self.checkmate.as_mut()),
off => UEnv::new(self.subs),
})
}

View file

@ -1,3 +1,4 @@
use crate::solve::RunSolveOutput;
use crate::FunctionKind;
use crate::{aliases::Aliases, solve};
use roc_can::abilities::{AbilitiesStore, ResolvedImpl};
@ -75,6 +76,10 @@ pub struct SolveConfig<'a> {
/// Needed during solving to resolve lambda sets from derived implementations that escape into
/// the user module.
pub derived_module: SharedDerivedModule,
#[cfg(debug_assertions)]
/// The checkmate collector for this module.
pub checkmate: Option<roc_checkmate::Collector>,
}
pub struct SolveOutput {
@ -82,6 +87,9 @@ pub struct SolveOutput {
pub scope: solve::Scope,
pub errors: Vec<TypeError>,
pub resolved_abilities_store: AbilitiesStore,
#[cfg(debug_assertions)]
pub checkmate: Option<roc_checkmate::Collector>,
}
pub fn run_solve(
@ -108,7 +116,12 @@ pub fn run_solve(
let mut problems = Vec::new();
// Run the solver to populate Subs.
let (solved_subs, solved_scope) = solve::run(
let RunSolveOutput {
solved,
scope,
#[cfg(debug_assertions)]
checkmate,
} = solve::run(
config,
&mut problems,
subs,
@ -117,10 +130,12 @@ pub fn run_solve(
);
SolveOutput {
subs: solved_subs,
scope: solved_scope,
subs: solved,
scope,
errors: problems,
resolved_abilities_store: abilities_store,
#[cfg(debug_assertions)]
checkmate,
}
}

View file

@ -94,27 +94,32 @@ struct State {
mark: Mark,
}
pub struct RunSolveOutput {
pub solved: Solved<Subs>,
pub scope: Scope,
#[cfg(debug_assertions)]
pub checkmate: Option<roc_checkmate::Collector>,
}
pub fn run(
config: SolveConfig,
problems: &mut Vec<TypeError>,
mut subs: Subs,
subs: Subs,
aliases: &mut Aliases,
abilities_store: &mut AbilitiesStore,
) -> (Solved<Subs>, Scope) {
let env = run_in_place(config, problems, &mut subs, aliases, abilities_store);
(Solved(subs), env)
) -> RunSolveOutput {
run_help(config, problems, subs, aliases, abilities_store)
}
/// Modify an existing subs in-place instead
#[allow(clippy::too_many_arguments)] // TODO: put params in a context/env var
fn run_in_place(
fn run_help(
config: SolveConfig,
problems: &mut Vec<TypeError>,
subs: &mut Subs,
mut owned_subs: Subs,
aliases: &mut Aliases,
abilities_store: &mut AbilitiesStore,
) -> Scope {
) -> RunSolveOutput {
let subs = &mut owned_subs;
let SolveConfig {
home: _,
constraints,
@ -124,6 +129,7 @@ fn run_in_place(
exposed_by_module,
derived_module,
function_kind,
..
} = config;
let mut pools = Pools::default();
@ -150,6 +156,8 @@ fn run_in_place(
derived_env: &derived_env,
subs,
pools: &mut pools,
#[cfg(debug_assertions)]
checkmate: config.checkmate,
};
let pending_derives = PendingDerivesTable::new(
@ -180,7 +188,12 @@ fn run_in_place(
&mut awaiting_specializations,
);
state.scope
RunSolveOutput {
scope: state.scope,
#[cfg(debug_assertions)]
checkmate: env.checkmate,
solved: Solved(owned_subs),
}
}
#[derive(Debug)]