Only compile and run expects that belong to the same package

In particular, don't run expects that come from modules with a different
package qualification (including subpackages; we can loosen this
restriction later), or builtins when run on userspace apps/interfaces.

Closes #3722
This commit is contained in:
ayazhafiz 2022-08-28 10:16:55 -05:00
parent f879798b17
commit 3456a44742
No known key found for this signature in database
GPG Key ID: B443F7A3030C9AED
2 changed files with 34 additions and 11 deletions

View File

@ -461,6 +461,9 @@ fn start_phase<'a>(
let derived_module = SharedDerivedModule::clone(&state.derived_module);
let build_expects = matches!(state.exec_mode, ExecutionMode::Test)
&& state.module_cache.expectations.contains_key(&module_id);
BuildTask::BuildPendingSpecializations {
layout_cache,
execution_mode: state.exec_mode,
@ -475,6 +478,7 @@ fn start_phase<'a>(
// TODO: awful, how can we get rid of the clone?
exposed_by_module: state.exposed_types.clone(),
derived_module,
build_expects,
}
}
Phase::MakeSpecializations => {
@ -1127,6 +1131,7 @@ enum BuildTask<'a> {
exposed_by_module: ExposedByModule,
abilities_store: AbilitiesStore,
derived_module: SharedDerivedModule,
build_expects: bool,
},
MakeSpecializations {
module_id: ModuleId,
@ -2358,7 +2363,14 @@ fn update<'a>(
.type_problems
.insert(module_id, solved_module.problems);
if !loc_expects.is_empty() {
let should_include_expects = !loc_expects.is_empty() && {
let modules = state.arc_modules.lock();
modules
.package_eq(module_id, state.root_id)
.expect("root or this module is not yet known - that's a bug!")
};
if should_include_expects {
let (path, _) = state.module_cache.sources.get(&module_id).unwrap();
let expectations = Expectations {
@ -4821,6 +4833,7 @@ fn build_pending_specializations<'a>(
exposed_by_module: &ExposedByModule,
abilities_store: AbilitiesStore,
derived_module: SharedDerivedModule,
build_expects: bool,
) -> Msg<'a> {
let find_specializations_start = Instant::now();
@ -5067,11 +5080,8 @@ fn build_pending_specializations<'a>(
}
Expectation => {
// skip expectations if we're not going to run them
match execution_mode {
ExecutionMode::Test => { /* fall through */ }
ExecutionMode::Check
| ExecutionMode::Executable
| ExecutionMode::ExecutableIfCheck => continue,
if !build_expects {
continue;
}
// mark this symbol as a top-level thunk before any other work on the procs
@ -5143,11 +5153,8 @@ fn build_pending_specializations<'a>(
}
ExpectationFx => {
// skip expectations if we're not going to run them
match execution_mode {
ExecutionMode::Test => { /* fall through */ }
ExecutionMode::Check
| ExecutionMode::Executable
| ExecutionMode::ExecutableIfCheck => continue,
if !build_expects {
continue;
}
// mark this symbol as a top-level thunk before any other work on the procs
@ -5433,6 +5440,7 @@ fn run_task<'a>(
abilities_store,
exposed_by_module,
derived_module,
build_expects,
} => Ok(build_pending_specializations(
arena,
execution_mode,
@ -5448,6 +5456,7 @@ fn run_task<'a>(
&exposed_by_module,
abilities_store,
derived_module,
build_expects,
)),
MakeSpecializations {
module_id,

View File

@ -512,6 +512,20 @@ impl<'a> PackageModuleIds<'a> {
pub fn available_modules(&self) -> impl Iterator<Item = &PQModuleName> {
self.by_id.iter()
}
/// Returns true iff two modules belong to the same package.
/// Returns [None] if one module is unknown.
pub fn package_eq(&self, left: ModuleId, right: ModuleId) -> Option<bool> {
if left.is_builtin() ^ right.is_builtin() {
return Some(false);
}
let result = match (self.get_name(left)?, self.get_name(right)?) {
(PQModuleName::Unqualified(_), PQModuleName::Unqualified(_)) => true,
(PQModuleName::Qualified(pkg1, _), PQModuleName::Qualified(pkg2, _)) => pkg1 == pkg2,
_ => false,
};
Some(result)
}
}
/// Stores a mapping between ModuleId and InlinableString.