mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
Dynamically load find/make specializations graph if there are no type errors
This commit is contained in:
parent
34c3f266e0
commit
b809d6d452
4 changed files with 153 additions and 12 deletions
|
@ -130,13 +130,15 @@ pub enum ExecutionMode {
|
|||
Test,
|
||||
Check,
|
||||
Executable,
|
||||
/// Like [`ExecutionMode::Executable`], but stops in the presence of type errors.
|
||||
ExecutableIfCheck,
|
||||
}
|
||||
|
||||
impl ExecutionMode {
|
||||
fn goal_phase(&self) -> Phase {
|
||||
match self {
|
||||
ExecutionMode::Test | ExecutionMode::Executable => Phase::MakeSpecializations,
|
||||
ExecutionMode::Check => Phase::SolveTypes,
|
||||
ExecutionMode::Check | ExecutionMode::ExecutableIfCheck => Phase::SolveTypes,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -168,6 +170,22 @@ struct ModuleCache<'a> {
|
|||
sources: MutMap<ModuleId, (PathBuf, &'a str)>,
|
||||
}
|
||||
|
||||
impl<'a> ModuleCache<'a> {
|
||||
pub fn total_problems(&self) -> usize {
|
||||
let mut total = 0;
|
||||
|
||||
for problems in self.can_problems.values() {
|
||||
total += problems.len();
|
||||
}
|
||||
|
||||
for problems in self.type_problems.values() {
|
||||
total += problems.len();
|
||||
}
|
||||
|
||||
total
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ModuleCache<'_> {
|
||||
fn default() -> Self {
|
||||
let mut module_names = MutMap::default();
|
||||
|
@ -2379,7 +2397,12 @@ fn update<'a>(
|
|||
.extend(solved_module.aliases.keys().copied());
|
||||
}
|
||||
|
||||
if is_host_exposed && state.goal_phase() == Phase::SolveTypes {
|
||||
let finish_type_checking = is_host_exposed &&
|
||||
(state.goal_phase() == Phase::SolveTypes)
|
||||
// If we're running in check-and-then-build mode, only exit now there are errors.
|
||||
&& (!matches!(state.exec_mode, ExecutionMode::ExecutableIfCheck) || state.module_cache.total_problems() > 0);
|
||||
|
||||
if finish_type_checking {
|
||||
debug_assert!(work.is_empty());
|
||||
debug_assert!(state.dependencies.solved_all());
|
||||
|
||||
|
@ -2421,7 +2444,9 @@ fn update<'a>(
|
|||
},
|
||||
);
|
||||
|
||||
if state.goal_phase() > Phase::SolveTypes {
|
||||
if state.goal_phase() > Phase::SolveTypes
|
||||
|| matches!(state.exec_mode, ExecutionMode::ExecutableIfCheck)
|
||||
{
|
||||
let layout_cache = state
|
||||
.layout_caches
|
||||
.pop()
|
||||
|
@ -2446,6 +2471,25 @@ fn update<'a>(
|
|||
state.timings.insert(module_id, module_timing);
|
||||
}
|
||||
|
||||
let work = if is_host_exposed
|
||||
&& matches!(state.exec_mode, ExecutionMode::ExecutableIfCheck)
|
||||
{
|
||||
debug_assert!(
|
||||
work.is_empty(),
|
||||
"work left over after host exposed is checked"
|
||||
);
|
||||
|
||||
// Update the goal phase to target full codegen.
|
||||
state.exec_mode = ExecutionMode::Executable;
|
||||
|
||||
// Load the find + make specializations portion of the dependency graph.
|
||||
state
|
||||
.dependencies
|
||||
.load_find_and_make_specializations_after_check()
|
||||
} else {
|
||||
work
|
||||
};
|
||||
|
||||
start_tasks(arena, &mut state, work, injector, worker_listeners)?;
|
||||
}
|
||||
|
||||
|
@ -2803,7 +2847,7 @@ fn finish_specialization(
|
|||
let entry_point = {
|
||||
match exec_mode {
|
||||
ExecutionMode::Test => EntryPoint::Test,
|
||||
ExecutionMode::Executable => {
|
||||
ExecutionMode::Executable | ExecutionMode::ExecutableIfCheck => {
|
||||
let path_to_platform = {
|
||||
use PlatformPath::*;
|
||||
let package_name = match platform_path {
|
||||
|
@ -5000,7 +5044,9 @@ fn build_pending_specializations<'a>(
|
|||
// skip expectations if we're not going to run them
|
||||
match execution_mode {
|
||||
ExecutionMode::Test => { /* fall through */ }
|
||||
ExecutionMode::Check | ExecutionMode::Executable => continue,
|
||||
ExecutionMode::Check
|
||||
| ExecutionMode::Executable
|
||||
| ExecutionMode::ExecutableIfCheck => continue,
|
||||
}
|
||||
|
||||
// mark this symbol as a top-level thunk before any other work on the procs
|
||||
|
@ -5074,7 +5120,9 @@ fn build_pending_specializations<'a>(
|
|||
// skip expectations if we're not going to run them
|
||||
match execution_mode {
|
||||
ExecutionMode::Test => { /* fall through */ }
|
||||
ExecutionMode::Check | ExecutionMode::Executable => continue,
|
||||
ExecutionMode::Check
|
||||
| ExecutionMode::Executable
|
||||
| ExecutionMode::ExecutableIfCheck => continue,
|
||||
}
|
||||
|
||||
// mark this symbol as a top-level thunk before any other work on the procs
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue