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 fxhash::FxBuildHasher;
|
||||||
use indexmap::IndexSet;
|
use indexmap::IndexSet;
|
||||||
use ref_thread_local::RefThreadLocal;
|
pub use ref_thread_local::RefThreadLocal;
|
||||||
|
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::fs::File;
|
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) {
|
pub(crate) fn add_module(
|
||||||
self.reset_in_situ_module(module_decl.clone(), &listing_src);
|
&mut self,
|
||||||
|
module_decl: ModuleDecl,
|
||||||
|
listing_src: ListingSource,
|
||||||
|
) -> Result<(), SessionError> {
|
||||||
let module_name = module_decl.name;
|
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) {
|
let mut module = match self.wam_prelude.indices.modules.remove(&module_name) {
|
||||||
Some(mut module) => {
|
Some(mut module) => {
|
||||||
module.listing_src = listing_src;
|
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);
|
self.wam_prelude.indices.modules.insert(module_name, module);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn import_module(&mut self, module_name: Atom) -> Result<(), SessionError> {
|
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>,
|
loader: &Loader<'a, Self>,
|
||||||
key: PredicateKey,
|
key: PredicateKey,
|
||||||
) -> Result<(), SessionError>;
|
) -> Result<(), SessionError>;
|
||||||
|
|
||||||
|
fn err_on_builtin_module_overwrite(_module_name: Atom) -> Result<(), SessionError> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LiveLoadAndMachineState<'a> {
|
pub struct LiveLoadAndMachineState<'a> {
|
||||||
@@ -353,6 +357,15 @@ impl<'a> LoadState<'a> for LiveLoadAndMachineState<'a> {
|
|||||||
|
|
||||||
Ok(())
|
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> {
|
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);
|
self.add_meta_predicate_record(module_name, name, meta_specs);
|
||||||
}
|
}
|
||||||
Declaration::Module(module_decl) => {
|
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;
|
self.payload.predicates.compilation_target = self.payload.compilation_target;
|
||||||
|
|
||||||
let listing_src = self.payload.term_stream.listing_src().clone();
|
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) => {
|
Declaration::NonCountedBacktracking(name, arity) => {
|
||||||
self.payload.non_counted_bt_preds.insert((name, arity));
|
self.payload.non_counted_bt_preds.insert((name, arity));
|
||||||
@@ -1849,9 +1864,7 @@ impl Machine {
|
|||||||
2,
|
2,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let path = cell_as_atom!(self
|
let path = cell_as_atom!(self.deref_register(2));
|
||||||
.machine_st
|
|
||||||
.store(self.machine_st.deref(self.machine_st.registers[2])));
|
|
||||||
|
|
||||||
self.load_contexts
|
self.load_contexts
|
||||||
.push(LoadContext::new(&*path.as_str(), stream));
|
.push(LoadContext::new(&*path.as_str(), stream));
|
||||||
|
|||||||
@@ -161,6 +161,26 @@ pub(crate) trait PermissionError {
|
|||||||
) -> MachineError;
|
) -> 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 {
|
impl PermissionError for HeapCellValue {
|
||||||
fn permission_error(
|
fn permission_error(
|
||||||
self,
|
self,
|
||||||
@@ -459,7 +479,6 @@ impl MachineState {
|
|||||||
pub(super) fn session_error(&mut self, err: SessionError) -> MachineError {
|
pub(super) fn session_error(&mut self, err: SessionError) -> MachineError {
|
||||||
match err {
|
match err {
|
||||||
SessionError::CannotOverwriteBuiltIn(key) => {
|
SessionError::CannotOverwriteBuiltIn(key) => {
|
||||||
// SessionError::CannotOverwriteImport(pred_atom) => {
|
|
||||||
self.permission_error(
|
self.permission_error(
|
||||||
Permission::Modify,
|
Permission::Modify,
|
||||||
atom!("static_procedure"),
|
atom!("static_procedure"),
|
||||||
@@ -468,10 +487,14 @@ impl MachineState {
|
|||||||
.collect::<MachineStub>(),
|
.collect::<MachineStub>(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
SessionError::CannotOverwriteBuiltInModule(module) => {
|
||||||
|
self.permission_error(
|
||||||
|
Permission::Modify,
|
||||||
|
atom!("static_module"),
|
||||||
|
module,
|
||||||
|
)
|
||||||
|
}
|
||||||
SessionError::ExistenceError(err) => self.existence_error(err),
|
SessionError::ExistenceError(err) => self.existence_error(err),
|
||||||
// SessionError::InvalidFileName(filename) => {
|
|
||||||
// Self::existence_error(h, ExistenceError::Module(filename))
|
|
||||||
// }
|
|
||||||
SessionError::ModuleDoesNotContainExport(..) => {
|
SessionError::ModuleDoesNotContainExport(..) => {
|
||||||
let error_atom = atom!("module_does_not_contain_claimed_export");
|
let error_atom = atom!("module_does_not_contain_claimed_export");
|
||||||
|
|
||||||
@@ -977,6 +1000,7 @@ pub enum ExistenceError {
|
|||||||
pub enum SessionError {
|
pub enum SessionError {
|
||||||
CompilationError(CompilationError),
|
CompilationError(CompilationError),
|
||||||
CannotOverwriteBuiltIn(PredicateKey),
|
CannotOverwriteBuiltIn(PredicateKey),
|
||||||
|
CannotOverwriteBuiltInModule(Atom),
|
||||||
ExistenceError(ExistenceError),
|
ExistenceError(ExistenceError),
|
||||||
ModuleDoesNotContainExport(Atom, PredicateKey),
|
ModuleDoesNotContainExport(Atom, PredicateKey),
|
||||||
ModuleCannotImportSelf(Atom),
|
ModuleCannotImportSelf(Atom),
|
||||||
|
|||||||
Reference in New Issue
Block a user