throw an error instead of allowing builtin modules to be overwritten (#2042)
This commit is contained in:
@@ -9,7 +9,7 @@ use crate::parser::ast::*;
|
||||
|
||||
use fxhash::FxBuildHasher;
|
||||
use indexmap::IndexSet;
|
||||
use ref_thread_local::RefThreadLocal;
|
||||
pub use ref_thread_local::RefThreadLocal;
|
||||
|
||||
use std::collections::VecDeque;
|
||||
use std::fs::File;
|
||||
@@ -1004,10 +1004,22 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn add_module(&mut self, module_decl: ModuleDecl, listing_src: ListingSource) {
|
||||
self.reset_in_situ_module(module_decl.clone(), &listing_src);
|
||||
pub(crate) fn add_module(
|
||||
&mut self,
|
||||
module_decl: ModuleDecl,
|
||||
listing_src: ListingSource,
|
||||
) -> Result<(), SessionError> {
|
||||
let module_name = module_decl.name;
|
||||
|
||||
if let Some(module) = self.wam_prelude.indices.modules.get(&module_name) {
|
||||
if let ListingSource::DynamicallyGenerated = module.listing_src {
|
||||
} else {
|
||||
LS::err_on_builtin_module_overwrite(module_name)?;
|
||||
}
|
||||
}
|
||||
|
||||
self.reset_in_situ_module(module_decl.clone(), &listing_src);
|
||||
|
||||
let mut module = match self.wam_prelude.indices.modules.remove(&module_name) {
|
||||
Some(mut module) => {
|
||||
module.listing_src = listing_src;
|
||||
@@ -1045,6 +1057,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
||||
}
|
||||
|
||||
self.wam_prelude.indices.modules.insert(module_name, module);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) fn import_module(&mut self, module_name: Atom) -> Result<(), SessionError> {
|
||||
|
||||
@@ -265,6 +265,10 @@ pub trait LoadState<'a>: Sized {
|
||||
loader: &Loader<'a, Self>,
|
||||
key: PredicateKey,
|
||||
) -> Result<(), SessionError>;
|
||||
|
||||
fn err_on_builtin_module_overwrite(_module_name: Atom) -> Result<(), SessionError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LiveLoadAndMachineState<'a> {
|
||||
@@ -353,6 +357,15 @@ impl<'a> LoadState<'a> for LiveLoadAndMachineState<'a> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn err_on_builtin_module_overwrite(module_name: Atom) -> Result<(), SessionError> {
|
||||
if LIBRARIES.borrow().contains_key(&*module_name.as_str()) {
|
||||
Err(SessionError::CannotOverwriteBuiltInModule(module_name))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> LoadState<'a> for BootstrappingLoadState<'a> {
|
||||
@@ -533,11 +546,13 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
||||
self.add_meta_predicate_record(module_name, name, meta_specs);
|
||||
}
|
||||
Declaration::Module(module_decl) => {
|
||||
self.payload.compilation_target = CompilationTarget::Module(module_decl.name);
|
||||
let module_name = module_decl.name;
|
||||
|
||||
self.payload.compilation_target = CompilationTarget::Module(module_name);
|
||||
self.payload.predicates.compilation_target = self.payload.compilation_target;
|
||||
|
||||
let listing_src = self.payload.term_stream.listing_src().clone();
|
||||
self.add_module(module_decl, listing_src);
|
||||
self.add_module(module_decl, listing_src)?;
|
||||
}
|
||||
Declaration::NonCountedBacktracking(name, arity) => {
|
||||
self.payload.non_counted_bt_preds.insert((name, arity));
|
||||
@@ -1849,9 +1864,7 @@ impl Machine {
|
||||
2,
|
||||
)?;
|
||||
|
||||
let path = cell_as_atom!(self
|
||||
.machine_st
|
||||
.store(self.machine_st.deref(self.machine_st.registers[2])));
|
||||
let path = cell_as_atom!(self.deref_register(2));
|
||||
|
||||
self.load_contexts
|
||||
.push(LoadContext::new(&*path.as_str(), stream));
|
||||
|
||||
@@ -161,6 +161,26 @@ pub(crate) trait PermissionError {
|
||||
) -> MachineError;
|
||||
}
|
||||
|
||||
impl PermissionError for Atom {
|
||||
fn permission_error(
|
||||
self,
|
||||
_machine_st: &mut MachineState,
|
||||
index_atom: Atom,
|
||||
perm: Permission,
|
||||
) -> MachineError {
|
||||
let stub = functor!(
|
||||
atom!("permission_error"),
|
||||
[atom(perm.as_atom()), atom(index_atom), cell(atom_as_cell!(self))]
|
||||
);
|
||||
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Received,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PermissionError for HeapCellValue {
|
||||
fn permission_error(
|
||||
self,
|
||||
@@ -459,7 +479,6 @@ impl MachineState {
|
||||
pub(super) fn session_error(&mut self, err: SessionError) -> MachineError {
|
||||
match err {
|
||||
SessionError::CannotOverwriteBuiltIn(key) => {
|
||||
// SessionError::CannotOverwriteImport(pred_atom) => {
|
||||
self.permission_error(
|
||||
Permission::Modify,
|
||||
atom!("static_procedure"),
|
||||
@@ -468,10 +487,14 @@ impl MachineState {
|
||||
.collect::<MachineStub>(),
|
||||
)
|
||||
}
|
||||
SessionError::CannotOverwriteBuiltInModule(module) => {
|
||||
self.permission_error(
|
||||
Permission::Modify,
|
||||
atom!("static_module"),
|
||||
module,
|
||||
)
|
||||
}
|
||||
SessionError::ExistenceError(err) => self.existence_error(err),
|
||||
// SessionError::InvalidFileName(filename) => {
|
||||
// Self::existence_error(h, ExistenceError::Module(filename))
|
||||
// }
|
||||
SessionError::ModuleDoesNotContainExport(..) => {
|
||||
let error_atom = atom!("module_does_not_contain_claimed_export");
|
||||
|
||||
@@ -977,6 +1000,7 @@ pub enum ExistenceError {
|
||||
pub enum SessionError {
|
||||
CompilationError(CompilationError),
|
||||
CannotOverwriteBuiltIn(PredicateKey),
|
||||
CannotOverwriteBuiltInModule(Atom),
|
||||
ExistenceError(ExistenceError),
|
||||
ModuleDoesNotContainExport(Atom, PredicateKey),
|
||||
ModuleCannotImportSelf(Atom),
|
||||
|
||||
Reference in New Issue
Block a user