UnexpandedGoals = ExpandedGoals
; goal_expansion(UnexpandedGoals, Module, UnexpandedGoals1),
( Module \== user ->
- goal_expansion(UnexpandedGoals1, user, ExpandedGoals)
+ goal_expansion(UnexpandedGoals1, user, Goals),
+ ( predicate_property(Module:Goals, meta_predicate(MetaSpecs0)),
+ MetaSpecs0 =.. [_ | MetaSpecs] ->
+ expand_module_names(Goals, MetaSpecs, Module, ExpandedGoals, HeadVars, TGs)
+ ; ExpandedGoals = Goals
+ )
; ExpandedGoals = UnexpandedGoals1
)
).
}
#[inline(always)]
- pub(crate) fn goal_expansion_defined(&self, key: PredicateKey) -> bool {
- self.goal_expansion_indices.contains(&key)
+ pub(crate) fn goal_expansion_defined(&self, key: PredicateKey, module_name: Atom) -> bool {
+ let compilation_target = match module_name {
+ atom!("user") => CompilationTarget::User,
+ _ => CompilationTarget::Module(module_name),
+ };
+
+ match key {
+ _ if self.goal_expansion_indices.contains(&key) => true,
+ _ => self
+ .get_meta_predicate_spec(key.0, key.1, &compilation_target)
+ .map(|meta_specs| {
+ meta_specs.iter().find(|meta_spec| match meta_spec {
+ MetaSpec::Colon | MetaSpec::RequiresExpansionWithArgument(_) => true,
+ _ => false,
+ })
+ })
+ .map(|meta_spec_opt| meta_spec_opt.is_some())
+ .unwrap_or(false),
+ }
}
pub(crate) fn get_predicate_skeleton_mut(
let index_cell = index_cell_opt.or_else(|| {
let is_internal_call = name == atom!("$call") && goal_arity > 0;
- if !is_internal_call && self.indices.goal_expansion_defined((name, arity)) {
- None
- } else {
- if is_internal_call {
- debug_assert_eq!(goal.get_tag(), HeapCellValueTag::Str);
- goal = self.machine_st.heap[goal.get_value() as usize + 1];
- (module_name, goal) = self.machine_st.strip_module(goal, module_name);
+ if !is_internal_call {
+ let module_name = if module_name.get_tag() == HeapCellValueTag::Atom {
+ cell_as_atom!(module_name)
+ } else {
+ atom!("user")
+ };
- if let Some((inner_name, inner_arity)) =
- self.machine_st.name_and_arity_from_heap(goal)
- {
- arity -= goal_arity;
- (name, goal_arity) = (inner_name, inner_arity);
- arity += goal_arity;
- } else {
- return None;
- }
+ if self
+ .indices
+ .goal_expansion_defined((name, arity), module_name)
+ {
+ return None;
}
+ }
- let module_name = if module_name.get_tag() != HeapCellValueTag::Atom {
- if let Some(load_context) = self.load_contexts.last() {
- load_context.module
- } else {
- atom!("user")
- }
- } else {
- cell_as_atom!(module_name)
- };
+ if is_internal_call {
+ debug_assert_eq!(goal.get_tag(), HeapCellValueTag::Str);
+ goal = self.machine_st.heap[goal.get_value() as usize + 1];
+ (module_name, goal) = self.machine_st.strip_module(goal, module_name);
- self.indices
- .get_predicate_code_index(name, arity, module_name)
+ if let Some((inner_name, inner_arity)) =
+ self.machine_st.name_and_arity_from_heap(goal)
+ {
+ arity -= goal_arity;
+ (name, goal_arity) = (inner_name, inner_arity);
+ arity += goal_arity;
+ } else {
+ return None;
+ }
}
+
+ let module_name = if module_name.get_tag() != HeapCellValueTag::Atom {
+ if let Some(load_context) = self.load_contexts.last() {
+ load_context.module
+ } else {
+ atom!("user")
+ }
+ } else {
+ cell_as_atom!(module_name)
+ };
+
+ self.indices
+ .get_predicate_code_index(name, arity, module_name)
});
if let Some(code_index) = index_cell {
--- /dev/null
+:- use_module(issue2361_m).
+
+:- initialization(gs([(length("a",_),length("ab",_))])).
--- /dev/null
+:- module(m, [gs/1]).
+
+:- use_module(library(lists)).
+
+gs([]).
+gs([G|Gs]) :-
+ G,
+ gs(Gs).
" error(existence_error(procedure,call/0),call/0).\n",
);
}
+
+// issue #2361
+#[serial]
+#[test]
+fn call_qualification() {
+ load_module_test("tests-pl/issue2361-call-qualified.pl", "");
+}