diff --git a/NEWS b/NEWS index 4508e198d..16631a759 100644 --- a/NEWS +++ b/NEWS @@ -10,7 +10,9 @@ Changes to the Mercury language: declarations and in the head of a clause for a user-defined field access function. * We now support impure higher-order code. -* We now allow user-defined comparison routines. +* We now allow user-defined comparison predicates. +* User-defined equality and comparison predicates for a type are now + required to be defined in the same module as the type. Changes to the Mercury compiler: * Better support for incremental program development: @@ -42,12 +44,15 @@ DETAILED LISTING Changes to the Mercury language: -* We now allow user-defined comparison routines, using the syntax +* We now allow user-defined comparison predicates, using the syntax :- type t ---> t where equality is unify_t, comparison is compare_t. See the "User-defined equality and comparison" chapter of the Mercury Language Reference Manual for details. +* User-defined equality and comparison predicates for a type are now + required to be defined in the same module as the type. + * Infix `.' is now accepted as a module name separator. Hence it is now possible to write io.write_string and list.member to mean the same thing as io__write_string and list__member, for instance. This diff --git a/compiler/hlds_out.m b/compiler/hlds_out.m index 24bf9a722..98a2cc875 100644 --- a/compiler/hlds_out.m +++ b/compiler/hlds_out.m @@ -1024,6 +1024,7 @@ hlds_out__marker_name(naive, "naive"). hlds_out__marker_name(psn, "psn"). hlds_out__marker_name(supp_magic, "supp_magic"). hlds_out__marker_name(context, "context"). +hlds_out__marker_name(calls_are_fully_qualified, "calls_are_fully_qualified"). hlds_out__marker_name(not_accessible_by_unqualifed_name, "not_accessible_by_unqualifed_name"). hlds_out__marker_name(not_accessible_by_partially_qualified_names, diff --git a/compiler/hlds_pred.m b/compiler/hlds_pred.m index 1c496582d..6cd7bf83c 100644 --- a/compiler/hlds_pred.m +++ b/compiler/hlds_pred.m @@ -373,7 +373,7 @@ % always fully qualified. For calls occurring in `.opt' files % this will return `is_fully_qualified', otherwise % `may_be_partially_qualified'. -:- func calls_are_fully_qualified(import_status) = is_fully_qualified. +:- func calls_are_fully_qualified(pred_markers) = is_fully_qualified. % Predicates can be marked with various boolean flags, called % "markers". @@ -508,6 +508,12 @@ % If the compiler cannot guarantee termination % then it must give an error message. + ; calls_are_fully_qualified + % All calls in this predicate are + % fully qualified. This occurs for + % predicates read from `.opt' files + % and compiler-generated predicates. + ; not_accessible_by_unqualifed_name % This predicate is not accessible by its % unqualified name. @@ -969,8 +975,8 @@ status_defined_in_this_module(pseudo_exported, yes). status_defined_in_this_module(exported_to_submodules, yes). status_defined_in_this_module(local, yes). -calls_are_fully_qualified(Status) = - ( Status = opt_imported -> +calls_are_fully_qualified(Markers) = + ( check_marker(Markers, calls_are_fully_qualified) -> is_fully_qualified ; may_be_partially_qualified ). diff --git a/compiler/intermod.m b/compiler/intermod.m index 5f3809a61..1c99c697e 100644 --- a/compiler/intermod.m +++ b/compiler/intermod.m @@ -922,7 +922,8 @@ intermod__qualify_instance_method(ModuleInfo, ; InstanceMethodDefn0 = name(InstanceMethodName0), PredOrFunc = predicate, - typecheck__resolve_pred_overloading(ModuleInfo, local, + init_markers(Markers), + typecheck__resolve_pred_overloading(ModuleInfo, Markers, MethodCallArgTypes, MethodCallTVarSet, InstanceMethodName0, InstanceMethodName, PredId), PredIds = [PredId | PredIds0], @@ -1123,7 +1124,9 @@ intermod__resolve_user_special_pred_overloading(ModuleInfo, SpecialId, map__lookup(SpecialPreds, SpecialId - TypeCtor, UnifyPredId), module_info_pred_info(ModuleInfo, UnifyPredId, UnifyPredInfo), pred_info_arg_types(UnifyPredInfo, TVarSet, _, ArgTypes), - typecheck__resolve_pred_overloading(ModuleInfo, local, ArgTypes, + init_markers(Markers0), + add_marker(Markers0, calls_are_fully_qualified, Markers), + typecheck__resolve_pred_overloading(ModuleInfo, Markers, ArgTypes, TVarSet, Pred0, Pred, UserEqPredId), intermod__add_proc(UserEqPredId, _, Info0, Info). @@ -1837,6 +1840,7 @@ intermod__should_output_marker(check_termination, no). intermod__should_output_marker(generate_inline, _) :- % This marker should only occur after the magic sets transformation. error("intermod__should_output_marker: generate_inline"). +intermod__should_output_marker(calls_are_fully_qualified, no). intermod__should_output_marker(not_accessible_by_unqualifed_name, no). intermod__should_output_marker(not_accessible_by_partially_qualified_names, no). diff --git a/compiler/make_hlds.m b/compiler/make_hlds.m index a53c25e69..338649b18 100644 --- a/compiler/make_hlds.m +++ b/compiler/make_hlds.m @@ -1310,7 +1310,8 @@ add_pragma_type_spec_2(Pragma0, Context, PredId, Clauses = clauses_info(ArgVarSet, VarTypes0, TVarNameMap, VarTypes0, Args, [Clause], TI_VarMap, TCI_VarMap, HasForeignClauses), - pred_info_get_markers(PredInfo0, Markers), + pred_info_get_markers(PredInfo0, Markers0), + add_marker(Markers0, calls_are_fully_qualified, Markers), map__init(Proofs), ( pred_info_is_imported(PredInfo0) -> @@ -3837,7 +3838,10 @@ add_special_pred_for_real(SpecialPredId, ), unify_proc__generate_clause_info(SpecialPredId, Type, TypeBody, Context, Module1, ClausesInfo), - pred_info_set_clauses_info(PredInfo1, ClausesInfo, PredInfo), + pred_info_set_clauses_info(PredInfo1, ClausesInfo, PredInfo2), + pred_info_get_markers(PredInfo2, Markers2), + add_marker(Markers2, calls_are_fully_qualified, Markers), + pred_info_set_markers(PredInfo2, Markers, PredInfo), map__det_update(Preds0, PredId, PredInfo, Preds), module_info_set_preds(Module1, Preds, Module). @@ -4274,7 +4278,11 @@ module_add_clause(ModuleInfo0, ClauseVarSet, PredOrFunc, PredName, Args0, Body, % opt_imported preds are initially tagged as imported and are % tagged as opt_imported only if/when we see a clause for them { Status = opt_imported -> - pred_info_set_import_status(PredInfo0, opt_imported, PredInfo1) + pred_info_set_import_status(PredInfo0, + opt_imported, PredInfo0a), + pred_info_get_markers(PredInfo0a, Markers0), + add_marker(Markers0, calls_are_fully_qualified, Markers1), + pred_info_set_markers(PredInfo0a, Markers1, PredInfo1) ; PredInfo1 = PredInfo0 }, @@ -4375,8 +4383,8 @@ module_add_clause(ModuleInfo0, ClauseVarSet, PredOrFunc, PredName, Args0, Body, % pred_info_all_procids(PredInfo6, ProcIds), ( ProcIds = [] -> - pred_info_get_markers(PredInfo6, Markers0), - add_marker(Markers0, infer_modes, Markers), + pred_info_get_markers(PredInfo6, Markers6), + add_marker(Markers6, infer_modes, Markers), pred_info_set_markers(PredInfo6, Markers, PredInfo) ; PredInfo = PredInfo6 diff --git a/compiler/post_typecheck.m b/compiler/post_typecheck.m index 886c2a9dd..4d879760a 100644 --- a/compiler/post_typecheck.m +++ b/compiler/post_typecheck.m @@ -467,11 +467,11 @@ post_typecheck__resolve_pred_overloading(PredId0, Args0, CallerPredInfo, % have the specified name and arity % pred_info_typevarset(CallerPredInfo, TVarSet), - pred_info_import_status(CallerPredInfo, Status), + pred_info_get_markers(CallerPredInfo, Markers), pred_info_clauses_info(CallerPredInfo, ClausesInfo), clauses_info_vartypes(ClausesInfo, VarTypes), map__apply_to_list(Args0, VarTypes, ArgTypes), - typecheck__resolve_pred_overloading(ModuleInfo, Status, + typecheck__resolve_pred_overloading(ModuleInfo, Markers, ArgTypes, TVarSet, PredName0, PredName, PredId) ; PredId = PredId0, @@ -638,9 +638,10 @@ resolve_aditi_builtin_overloading(ModuleInfo, CallerPredInfo, Args, EvalMethod \= normal -> call(AdjustArgTypes, ArgTypes0, ArgTypes), - pred_info_import_status(CallerPredInfo, Status), - typecheck__resolve_pred_overloading(ModuleInfo, Status, - ArgTypes, TVarSet, SymName0, SymName, PredId) + pred_info_get_markers(CallerPredInfo, Markers), + typecheck__resolve_pred_overloading(ModuleInfo, + Markers, ArgTypes, TVarSet, + SymName0, SymName, PredId) ; error( "post_typecheck__resolve_aditi_builtin_overloading") @@ -1246,10 +1247,10 @@ post_typecheck__resolve_unify_functor(X0, ConsId0, ArgVars0, Mode0, % \+ pred_info_is_field_access_function(ModuleInfo, PredInfo0), - pred_info_import_status(PredInfo0, Status), + pred_info_get_markers(PredInfo0, Markers), module_info_get_predicate_table(ModuleInfo, PredTable), predicate_table_search_func_sym_arity(PredTable, - calls_are_fully_qualified(Status), + calls_are_fully_qualified(Markers), PredName, Arity, PredIds), % Check if any of the candidate functions have @@ -1300,8 +1301,8 @@ post_typecheck__resolve_unify_functor(X0, ConsId0, ArgVars0, Mode0, map__apply_to_list(ArgVars0, VarTypes0, ArgTypes0), AllArgTypes = ArgTypes0 ++ HOArgTypes, pred_info_typevarset(PredInfo0, TVarSet), - pred_info_import_status(PredInfo0, Status), - get_pred_id(calls_are_fully_qualified(Status), Name, + pred_info_get_markers(PredInfo0, Markers), + get_pred_id(calls_are_fully_qualified(Markers), Name, PredOrFunc, TVarSet, AllArgTypes, ModuleInfo, PredId) -> get_proc_id(ModuleInfo, PredId, ProcId), diff --git a/compiler/prog_io.m b/compiler/prog_io.m index 06512f25c..76445dee7 100644 --- a/compiler/prog_io.m +++ b/compiler/prog_io.m @@ -185,7 +185,8 @@ :- pred parse_type_defn_head(module_name, term, term, maybe_functor). :- mode parse_type_defn_head(in, in, in, out) is det. - % get_maybe_equality_compare_preds(Body0, Body, MaybeEqualPred): + % get_maybe_equality_compare_preds(ModuleName, + % Body0, Body, MaybeEqualPred): % Checks if `Body0' is a term of the form % ` where equality is ' % ` where comparison is ' @@ -195,9 +196,9 @@ % MaybeEqualPred. If not, returns Body = Body0 % and `no' in MaybeEqualPred. -:- pred get_maybe_equality_compare_preds(term, term, +:- pred get_maybe_equality_compare_preds(module_name, term, term, maybe1(maybe(unify_compare))). -:- mode get_maybe_equality_compare_preds(in, out, out) is det. +:- mode get_maybe_equality_compare_preds(in, in, out, out) is det. %-----------------------------------------------------------------------------% @@ -1522,7 +1523,7 @@ add_error(Error, Term, Msgs, [Msg - Term | Msgs]) :- parse_type_decl_type(ModuleName, "--->", [H, B], Condition, R) :- /* get_condition(...), */ Condition = true, - get_maybe_equality_compare_preds(B, Body, EqCompare), + get_maybe_equality_compare_preds(ModuleName, B, Body, EqCompare), process_du_type(ModuleName, H, Body, EqCompare, R). parse_type_decl_type(ModuleName, "==", [H, B], Condition, R) :- @@ -1645,7 +1646,7 @@ parse_mode_decl_pred(ModuleName, VarSet, Pred, Attributes, Result) :- %-----------------------------------------------------------------------------% -get_maybe_equality_compare_preds(B, Body, MaybeEqComp) :- +get_maybe_equality_compare_preds(ModuleName, B, Body, MaybeEqComp) :- ( B = term__functor(term__atom("where"), Args, _Context1), Args = [Body1, EqCompTerm] @@ -1655,14 +1656,16 @@ get_maybe_equality_compare_preds(B, Body, MaybeEqComp) :- parse_equality_or_comparison_pred_term("equality", EqCompTerm, PredName) -> - parse_symbol_name(PredName, MaybeEqComp0), + parse_implicitly_qualified_symbol_name(ModuleName, + PredName, MaybeEqComp0), process_maybe1(make_equality, MaybeEqComp0, MaybeEqComp) ; parse_equality_or_comparison_pred_term("comparison", EqCompTerm, PredName) -> - parse_symbol_name(PredName, MaybeEqComp0), + parse_implicitly_qualified_symbol_name(ModuleName, + PredName, MaybeEqComp0), process_maybe1(make_comparison, MaybeEqComp0, MaybeEqComp) ; @@ -1673,9 +1676,10 @@ get_maybe_equality_compare_preds(B, Body, MaybeEqComp) :- parse_equality_or_comparison_pred_term("comparison", CompTerm, CompPredNameTerm) -> - parse_symbol_name(EqPredNameTerm, EqPredNameResult), - parse_symbol_name(CompPredNameTerm, - CompPredNameResult), + parse_implicitly_qualified_symbol_name(ModuleName, + EqPredNameTerm, EqPredNameResult), + parse_implicitly_qualified_symbol_name(ModuleName, + CompPredNameTerm, CompPredNameResult), ( EqPredNameResult = ok(EqPredName), CompPredNameResult = ok(CompPredName), diff --git a/compiler/prog_io_pragma.m b/compiler/prog_io_pragma.m index 2e74a9a55..b62c9c2ad 100644 --- a/compiler/prog_io_pragma.m +++ b/compiler/prog_io_pragma.m @@ -37,7 +37,7 @@ parse_pragma(ModuleName, VarSet, PragmaTerms, Result) :- ( % new syntax: `:- pragma foo(...).' PragmaTerms = [SinglePragmaTerm0], - get_maybe_equality_compare_preds(SinglePragmaTerm0, + get_maybe_equality_compare_preds(ModuleName, SinglePragmaTerm0, SinglePragmaTerm, UnifyCompareResult), SinglePragmaTerm = term__functor(term__atom(PragmaType), PragmaArgs, _), diff --git a/compiler/purity.m b/compiler/purity.m index 1db8d874e..62fd9cf0f 100644 --- a/compiler/purity.m +++ b/compiler/purity.m @@ -754,9 +754,9 @@ check_higher_order_purity(GoalInfo, ConsId, Var, Args, ActualPurity) --> { list__append(ArgTypes0, VarArgTypes, PredArgTypes) }, ModuleInfo =^ module_info, CallerPredInfo =^ pred_info, - { pred_info_import_status(CallerPredInfo, CallerStatus) }, + { pred_info_get_markers(CallerPredInfo, CallerMarkers) }, ( - { get_pred_id(calls_are_fully_qualified(CallerStatus), + { get_pred_id(calls_are_fully_qualified(CallerMarkers), PName, PredOrFunc, TVarSet, PredArgTypes, ModuleInfo, CalleePredId) } -> diff --git a/compiler/typecheck.m b/compiler/typecheck.m index f11734f88..013652573 100644 --- a/compiler/typecheck.m +++ b/compiler/typecheck.m @@ -127,7 +127,7 @@ % Abort if there is no matching pred. % Abort if there are multiple matching preds. -:- pred typecheck__resolve_pred_overloading(module_info, import_status, +:- pred typecheck__resolve_pred_overloading(module_info, pred_markers, list(type), tvarset, sym_name, sym_name, pred_id). :- mode typecheck__resolve_pred_overloading(in, in, in, in, in, out, out) is det. @@ -471,10 +471,11 @@ typecheck_pred_type(Iteration, PredId, !PredInfo, ; IsFieldAccessFunction = no ), + pred_info_get_markers(!.PredInfo, Markers), typecheck_info_init(!.IOState, ModuleInfo, PredId, IsFieldAccessFunction, TypeVarSet0, VarSet, ExplicitVarTypes0, HeadTypeParams1, - Constraints, Status, TypeCheckInfo1), + Constraints, Status, Markers, TypeCheckInfo1), typecheck_info_get_type_assign_set(TypeCheckInfo1, OrigTypeAssignSet), typecheck_clause_list(Clauses1, HeadVars, ArgTypes0, Clauses, @@ -927,7 +928,10 @@ maybe_add_field_access_function_clause(ModuleInfo, PredInfo0, PredInfo) :- Clause = clause(ProcIds, Goal, mercury, Context), clauses_info_set_clauses(ClausesInfo0, [Clause], ClausesInfo), pred_info_update_goal_type(PredInfo0, clauses, PredInfo1), - pred_info_set_clauses_info(PredInfo1, ClausesInfo, PredInfo) + pred_info_set_clauses_info(PredInfo1, ClausesInfo, PredInfo2), + pred_info_get_markers(PredInfo2, Markers0), + add_marker(Markers0, calls_are_fully_qualified, Markers), + pred_info_set_markers(PredInfo2, Markers, PredInfo) ; PredInfo = PredInfo0 ). @@ -1703,7 +1707,7 @@ typecheck_call_pred_adjust_arg_types(CallId, Args, AdjustArgTypes, CallId = PorF - SymName/Arity, predicate_table_search_pf_sym_arity(PredicateTable, calls_are_fully_qualified( - TypeCheckInfo1 ^ import_status), + TypeCheckInfo1 ^ pred_markers), PorF, SymName, Arity, PredIdList) -> % handle the case of a non-overloaded predicate specially @@ -1806,7 +1810,7 @@ report_pred_call_error(PredCallId, TypeCheckInfo1, TypeCheckInfo) :- ( predicate_table_search_pf_sym(PredicateTable, calls_are_fully_qualified( - TypeCheckInfo1 ^ import_status), + TypeCheckInfo1 ^ pred_markers), PredOrFunc0, SymName, OtherIds), predicate_table_get_preds(PredicateTable, Preds), OtherIds \= [] @@ -1820,7 +1824,7 @@ report_pred_call_error(PredCallId, TypeCheckInfo1, TypeCheckInfo) :- ), predicate_table_search_pf_sym(PredicateTable, calls_are_fully_qualified( - TypeCheckInfo1 ^ import_status), + TypeCheckInfo1 ^ pred_markers), PredOrFunc, SymName, OtherIds), OtherIds \= [] -> @@ -1895,12 +1899,13 @@ get_overloaded_pred_arg_types([PredId | PredIds], Preds, AdjustArgTypes, % module qualified, so they should not be considered % when resolving overloading. -typecheck__resolve_pred_overloading(ModuleInfo, Status, ArgTypes, TVarSet, - PredName0, PredName, PredId) :- +typecheck__resolve_pred_overloading(ModuleInfo, CallerMarkers, + ArgTypes, TVarSet, PredName0, PredName, PredId) :- module_info_get_predicate_table(ModuleInfo, PredTable), ( predicate_table_search_pred_sym(PredTable, - calls_are_fully_qualified(Status), PredName0, PredIds0) + calls_are_fully_qualified(CallerMarkers), + PredName0, PredIds0) -> PredIds = PredIds0 ; @@ -3058,7 +3063,7 @@ builtin_pred_type(TypeCheckInfo, Functor, Arity, PredConsInfoList) :- ( predicate_table_search_sym(PredicateTable, calls_are_fully_qualified( - TypeCheckInfo ^ import_status), + TypeCheckInfo ^ pred_markers), SymName, PredIdList) -> predicate_table_get_preds(PredicateTable, Preds), @@ -3536,6 +3541,9 @@ project_rename_flip_class_constraints(CallTVars, TVarRenaming, % Import status of the pred % being checked + pred_markers :: pred_markers, + % Markers of the pred being checked + is_field_access_function :: bool, % Is the pred we're checking % a field access function? @@ -3577,7 +3585,7 @@ project_rename_flip_class_constraints(CallTVars, TVarRenaming, /* :- inst uniq_typecheck_info = bound_unique( typecheck_info( - unique, ground, + unique, ground, ground, ground, ground, ground, ground, ground, ground, ground, ground, ground, ground, ground @@ -3596,7 +3604,7 @@ project_rename_flip_class_constraints(CallTVars, TVarRenaming, /* :- inst typecheck_info_no_io = bound_unique( typecheck_info( - dead, ground, + dead, ground, ground, ground, ground, ground, ground, ground, ground, ground, ground, ground, ground, ground @@ -3615,14 +3623,14 @@ project_rename_flip_class_constraints(CallTVars, TVarRenaming, :- pred typecheck_info_init(io__state, module_info, pred_id, bool, tvarset, prog_varset, map(prog_var, type), headtypes, class_constraints, - import_status, typecheck_info). -:- mode typecheck_info_init(di, in, in, in, in, in, in, in, in, in, + import_status, pred_markers, typecheck_info). +:- mode typecheck_info_init(di, in, in, in, in, in, in, in, in, in, in, typecheck_info_uo) is det. typecheck_info_init(IOState0, ModuleInfo, PredId, IsFieldAccessFunction, TypeVarSet, VarSet, VarTypes, HeadTypeParams, - Constraints, Status, TypeCheckInfo) :- + Constraints, Status, Markers, TypeCheckInfo) :- CallPredId = call(predicate - unqualified("") / 0), term__context_init(Context), map__init(TypeBindings), @@ -3631,7 +3639,7 @@ typecheck_info_init(IOState0, ModuleInfo, PredId, IsFieldAccessFunction, WarnedAboutOverloading = no, unsafe_promise_unique(IOState0, IOState), % XXX TypeCheckInfo = typecheck_info( - IOState, ModuleInfo, CallPredId, 0, PredId, Status, + IOState, ModuleInfo, CallPredId, 0, PredId, Status, Markers, IsFieldAccessFunction, Context, unify_context(explicit, []), VarSet, [type_assign(VarTypes, TypeVarSet, HeadTypeParams, diff --git a/doc/reference_manual.texi b/doc/reference_manual.texi index 14ad876ac..d880352ff 100644 --- a/doc/reference_manual.texi +++ b/doc/reference_manual.texi @@ -3465,6 +3465,12 @@ could be any of @samp{det}, @samp{failure} or @samp{erroneous}). @item The equality predicate must be ``pure'' (@pxref{Impurity}). +@item +The equality predicate must be defined in the same module as the type. + +@item +If the type is exported the equality predicate must also be exported. + @item @var{equalitypred} should be an equivalence relation; that is, it must be symmetric, reflexive, and transitive. However, the compiler is not required @@ -3535,6 +3541,12 @@ determinism to be more permissive. @item The comparison predicate must also be ``pure'' (@pxref{Impurity}). +@item +The comparison predicate must be defined in the same module as the type. + +@item +If the type is exported the comparison predicate must also be exported. + @item The relation @example diff --git a/tests/invalid/Mmakefile b/tests/invalid/Mmakefile index a71422350..7cc1db660 100644 --- a/tests/invalid/Mmakefile +++ b/tests/invalid/Mmakefile @@ -16,6 +16,8 @@ MULTIMODULE_PROGS= \ aditi_update_errors \ aditi_update_mode_errors \ duplicate_instance_2 \ + exported_unify \ + exported_unify3 \ ho_default_func_2.sub \ import_in_parent \ imported_mode \ diff --git a/tests/invalid/exported_unify.err_exp b/tests/invalid/exported_unify.err_exp new file mode 100644 index 000000000..fa93cf37c --- /dev/null +++ b/tests/invalid/exported_unify.err_exp @@ -0,0 +1,3 @@ +exported_unify2.int:003: In clause for unification predicate for type (exported_unify2.foo): +exported_unify2.int:003: error: undefined predicate `exported_unify2.unify_foo/2'. +For more information, try recompiling with `-E'. diff --git a/tests/invalid/exported_unify.m b/tests/invalid/exported_unify.m new file mode 100644 index 000000000..238c86724 --- /dev/null +++ b/tests/invalid/exported_unify.m @@ -0,0 +1,13 @@ +:- module exported_unify. + +:- interface. + +:- pred unify_foo(T::in, T::in) is semidet. + +:- implementation. + +:- import_module exported_unify2. + +unify_foo(A, A). + + diff --git a/tests/invalid/exported_unify2.m b/tests/invalid/exported_unify2.m new file mode 100644 index 000000000..f3ababf01 --- /dev/null +++ b/tests/invalid/exported_unify2.m @@ -0,0 +1,14 @@ +:- module exported_unify2. + +:- interface. + +:- type foo ---> foo where equality is unify_foo. + +:- implementation. + +:- import_module std_util. + +:- pred unify_foo(foo::in, foo::in) is semidet. + +unify_foo(_, _) :- semidet_fail. + diff --git a/tests/invalid/exported_unify3.err_exp b/tests/invalid/exported_unify3.err_exp new file mode 100644 index 000000000..4829d6738 --- /dev/null +++ b/tests/invalid/exported_unify3.err_exp @@ -0,0 +1,7 @@ +exported_unify3.m:005: In clause for unification predicate for type (exported_unify3.foo): +exported_unify3.m:005: error: undefined predicate `exported_unify3.defined_in_wrong_module/2'. +exported_unify3.sub.int:003: In clause for unification predicate for type ((exported_unify3.sub).bar): +exported_unify3.sub.int:003: error: undefined predicate `exported_unify3.sub.not_exported/2'. +exported_unify3.int0:003: In clause for unification predicate for type (exported_unify3.foo): +exported_unify3.int0:003: error: undefined predicate `exported_unify3.defined_in_wrong_module/2'. +For more information, try recompiling with `-E'. diff --git a/tests/invalid/exported_unify3.m b/tests/invalid/exported_unify3.m new file mode 100644 index 000000000..2fb70915c --- /dev/null +++ b/tests/invalid/exported_unify3.m @@ -0,0 +1,33 @@ +:- module exported_unify3. + +:- interface. + +:- type foo ---> foo where equality is defined_in_wrong_module. + + :- module exported_unify3.sub. + + :- interface. + + :- type bar ---> bar where equality is not_exported. + + :- pred defined_in_wrong_module(foo::in, foo::in) is semidet. + + :- end_module exported_unify3.sub. + +:- implementation. + +:- import_module exported_unify3.sub. + + :- module exported_unify3.sub. + + :- implementation. + + :- import_module std_util. + + defined_in_wrong_module(_, _) :- semidet_fail. + + :- pred not_exported(bar::in, bar::in) is semidet. + + not_exported(_, _) :- semidet_fail. + + :- end_module exported_unify3.sub.