Revert "idea (rejected): only generate work up to constraint gen, then look at what modules are actually used and generate Solve.. work based on that"

This reverts commit 2cbe5f5231.
This commit is contained in:
Folkert 2022-03-19 16:26:46 +01:00
parent 2cbe5f5231
commit e914272bf5
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
5 changed files with 23 additions and 156 deletions

View file

@ -157,8 +157,6 @@ pub fn build_file<'a>(
buf.push('\n');
dbg!(module_id);
report_timing(buf, "Read .roc file from disk", module_timing.read_roc_file);
report_timing(buf, "Parse header", module_timing.parse_header);
report_timing(buf, "Parse body", module_timing.parse_body);

View file

@ -32,21 +32,13 @@ impl ExposedByModule {
///
/// Useful when we know what modules a particular module imports, and want just
/// the exposed types for those exposed modules.
pub fn retain_modules<'a>(
&self,
home: ModuleId,
it: impl Iterator<Item = &'a ModuleId>,
) -> Self {
pub fn retain_modules<'a>(&self, it: impl Iterator<Item = &'a ModuleId>) -> Self {
let mut output = Self::default();
for module_id in it {
match self.exposed.get(module_id) {
None => {
internal_error!(
"Module {:?} did not register its exposed values for {:?}",
module_id,
home,
)
internal_error!("Module {:?} did not register its exposed values", module_id)
}
Some(exposed_types) => {
output.exposed.insert(*module_id, exposed_types.clone());

View file

@ -1099,7 +1099,7 @@ fn load<'a>(
) -> Result<LoadResult<'a>, LoadingProblem<'a>> {
// When compiling to wasm, we cannot spawn extra threads
// so we have a single-threaded implementation
if cfg!(target_family = "wasm") {
if true || cfg!(target_family = "wasm") {
load_single_threaded(
arena,
load_start,
@ -1614,18 +1614,14 @@ fn report_unused_imported_modules<'a>(
state: &mut State<'a>,
module_id: ModuleId,
constrained_module: &ConstrainedModule,
) -> (Vec<ModuleId>, Vec<ModuleId>) {
let mut kept = vec![];
let mut removed = vec![];
) {
let mut unused_imported_modules = constrained_module.imported_modules.clone();
for symbol in constrained_module.module.referenced_values.iter() {
kept.push(symbol.module_id());
unused_imported_modules.remove(&symbol.module_id());
}
for symbol in constrained_module.module.referenced_types.iter() {
kept.push(symbol.module_id());
unused_imported_modules.remove(&symbol.module_id());
}
@ -1637,23 +1633,8 @@ fn report_unused_imported_modules<'a>(
for (unused, region) in unused_imported_modules.drain() {
if !unused.is_builtin() {
existing.push(roc_problem::can::Problem::UnusedImport(unused, region));
// we will still typecheck this module to report errors
kept.push(unused)
} else {
// for builtin modules, we will just skip the rest of the process
// in the future, we can also do this for modules from packages
removed.push(unused);
}
}
kept.sort();
kept.dedup();
removed.sort();
removed.dedup();
(kept, removed)
}
fn update<'a>(
@ -1889,7 +1870,7 @@ fn update<'a>(
work.extend(state.dependencies.add_module(
header.module_id,
&header.package_qualified_imported_modules,
Phase::CanonicalizeAndConstrain,
state.goal_phase,
));
state.module_cache.headers.insert(header.module_id, header);
@ -1938,7 +1919,7 @@ fn update<'a>(
}
CanonicalizedAndConstrained {
mut constrained_module,
constrained_module,
canonicalization_problems,
module_docs,
} => {
@ -1953,51 +1934,7 @@ fn update<'a>(
state.module_cache.documentation.insert(module_id, docs);
}
let (kept, removed) =
report_unused_imported_modules(&mut state, module_id, &constrained_module);
for rem in removed {
constrained_module.imported_modules.remove(&rem);
}
use std::fmt::Write;
let mut buf = String::new();
writeln!(buf, "{:?} depends on:", module_id);
for dep in kept {
if !constrained_module.imported_modules.contains_key(&dep) {
continue;
}
writeln!(buf, " {:?} ", dep);
if module_id != dep {
state
.dependencies
.add_dependency(module_id, dep, Phase::SolveTypes);
}
}
println!("{}", buf);
state.dependencies.add_dependency_help(
module_id,
module_id,
Phase::SolveTypes,
Phase::CanonicalizeAndConstrain,
);
state
.dependencies
.add_to_status(module_id, Phase::SolveTypes);
/*
for dependency in remove_dependencies {
println!("remove dep {:?} <- {:?}", module_id, dependency);
state.dependencies.remove_dependencies(
module_id,
dependency,
Phase::SolveTypes,
state.goal_phase,
);
}
*/
report_unused_imported_modules(&mut state, module_id, &constrained_module);
state
.module_cache
@ -2059,7 +1996,7 @@ fn update<'a>(
if is_host_exposed && state.goal_phase == Phase::SolveTypes {
debug_assert!(work.is_empty());
// debug_assert!(state.dependencies.solved_all());
debug_assert!(state.dependencies.solved_all());
state.timings.insert(module_id, module_timing);
@ -2850,7 +2787,10 @@ fn load_module<'a>(
roc_parse::header::ModuleName::new("Bool"),
Collection::with_items(&[Loc::at_zero(Spaced::Item(ExposedName::new("Bool")))]),
)),
// Note: List is only used for the type, which we ensure is always in scope
Loc::at_zero(ImportsEntry::Module(
roc_parse::header::ModuleName::new("List"),
Collection::with_items(&[Loc::at_zero(Spaced::Item(ExposedName::new("List")))]),
)),
Loc::at_zero(ImportsEntry::Module(
roc_parse::header::ModuleName::new("Num"),
Collection::with_items(&[
@ -2916,6 +2856,9 @@ fn load_module<'a>(
toUtf8 : Str -> List U8
# fromUtf8 : List U8 -> Result Str [ BadUtf8 Utf8Problem ]*
# fromUtf8Range : List U8 -> Result Str [ BadUtf8 Utf8Problem Nat, OutOfBounds ]*
fromUtf8 : List U8 -> Result Str [ BadUtf8 Utf8ByteProblem Nat ]*
fromUtf8Range : List U8, { start : Nat, count : Nat } -> Result Str [ BadUtf8 Utf8ByteProblem Nat, OutOfBounds ]*
@ -4401,8 +4344,7 @@ impl<'a> BuildTask<'a> {
dep_idents: MutMap<ModuleId, IdentIds>,
declarations: Vec<Declaration>,
) -> Self {
let exposed_by_module =
exposed_types.retain_modules(module.module_id, imported_modules.keys());
let exposed_by_module = exposed_types.retain_modules(imported_modules.keys());
let exposed_for_module =
ExposedForModule::new(module.referenced_values.iter(), exposed_by_module);
@ -4693,10 +4635,6 @@ fn canonicalize_and_constrain<'a>(
let constraint =
constrain_module(&mut constraints, &module_output.declarations, module_id);
if module_id == ModuleId::STR {
dbg!(&constraints);
}
let after = roc_types::types::get_type_clone_count();
log!(

View file

@ -32,7 +32,7 @@ enum Status {
Done,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
enum Job<'a> {
Step(ModuleId, Phase),
ResolveShorthand(&'a str),
@ -74,10 +74,8 @@ impl<'a> Dependencies<'a> {
// to canonicalize a module, all its dependencies must be canonicalized
self.add_dependency(module_id, dep, Phase::CanonicalizeAndConstrain);
if goal_phase >= Phase::SolveTypes {
// to typecheck a module, all its dependencies must be type checked already
self.add_dependency(module_id, dep, Phase::SolveTypes);
}
// to typecheck a module, all its dependencies must be type checked already
self.add_dependency(module_id, dep, Phase::SolveTypes);
if goal_phase >= FindSpecializations {
self.add_dependency(module_id, dep, Phase::FindSpecializations);
@ -103,7 +101,7 @@ impl<'a> Dependencies<'a> {
output
}
pub fn add_to_status(&mut self, module_id: ModuleId, goal_phase: Phase) {
fn add_to_status(&mut self, module_id: ModuleId, goal_phase: Phase) {
for phase in PHASES.iter() {
if *phase > goal_phase {
break;
@ -195,72 +193,13 @@ impl<'a> Dependencies<'a> {
}
}
pub fn remove_dependencies(
&mut self,
a: ModuleId,
b: ModuleId,
start_phase: Phase,
goal_phase: Phase,
) {
let mut i = 0;
while PHASES[i] < goal_phase {
let phase = PHASES[i];
if phase >= start_phase {
self.remove_dependency(a, b, phase);
}
i += 1;
}
}
/// A waits for B, and B will notify A when it completes the phase
/// we will remove both of these connections
fn remove_dependency(&mut self, a: ModuleId, b: ModuleId, phase: Phase) {
let key = Job::Step(a, phase);
let mut notifications = vec![];
match self.waiting_for.get_mut(&key) {
None => unreachable!(),
Some(x) => {
x.retain(|job| match job {
Job::Step(module, _) => {
if *module == b {
notifications.push(*job);
false
} else {
true
}
}
Job::ResolveShorthand(_) => true,
});
}
}
for notification in notifications {
match self.notifies.get_mut(&notification) {
None => unreachable!(),
Some(x) => {
x.retain(|notify_job| notify_job != &key);
}
}
}
}
/// A waits for B, and B will notify A when it completes the phase
pub fn add_dependency(&mut self, a: ModuleId, b: ModuleId, phase: Phase) {
fn add_dependency(&mut self, a: ModuleId, b: ModuleId, phase: Phase) {
self.add_dependency_help(a, b, phase, phase);
}
/// phase_a of module a is waiting for phase_b of module_b
pub fn add_dependency_help(
&mut self,
a: ModuleId,
b: ModuleId,
phase_a: Phase,
phase_b: Phase,
) {
fn add_dependency_help(&mut self, a: ModuleId, b: ModuleId, phase_a: Phase, phase_b: Phase) {
// no need to wait if the dependency is already done!
if let Some(Status::Done) = self.status.get(&Job::Step(b, phase_b)) {
return;

View file

@ -293,7 +293,7 @@ lazy_static! {
}
/// A globally unique ID that gets assigned to each module as it is loaded.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct ModuleId(u32);
impl ModuleId {