[m-rev.] for review: delete obsolete predicates from builtin module

Julien Fischer jfischer at opturion.com
Wed Apr 13 14:49:13 AEST 2022


For review by anyone.

The request for review is for the NEWS file and as a chance for any 
last-second objections; the diff itself is trivial.

----------------------------

Delete obsolete predicates from builtin module.

library/builtin:
     Delete the promise_only_solution/1 and promise_only_solution_io/4. Both
     have have been marked as obsolete since 2015.

     Also delete the non-public impure versions of those, get_one_solution/1
     and get_one_solution_io/4. Implementing the pure versions was the only
     use of these.

compiler/hlds_goal.m:
     Delete a reference to promise_only_solution in a comment.

tests/declarative_debugger/trust.exp:
tests/declarative_debugger/trust.inp:
tests/declarative_debugger/trust_1.m:
      Replace a call to promise_only_solution/1; this does simplify this test
      a little, but does not affect what the trust_1 module was testing, namely
      the user-defined comparison on the type exported by that module.

tests/declarative_debugger/exceptions.m:
tests/hard_coded/myset.m:
tests/hard_coded/user_compare.m:
tests/valid_seq/intermod_nested_module_bug2.m:
extras/curs/samples/nibbles.m:
      Replace calls to the now deleted predicates.

Julien.

diff --git a/NEWS b/NEWS
index 9f23c5f..70c8d33 100644
--- a/NEWS
+++ b/NEWS
@@ -55,9 +55,16 @@ Changes to the Mercury standard library
      - pred `write_bitmap_range/5`
      - pred `write_bitmap_range/6`

+### Changes to the `builtin` module
+
+* The following obsolete predicate and function have been removed:
+
+    - func `promise_only_solution/1`
+    - pred `promise_only_solution_io/4`
+
  ### Changes to the `hash_table` module

-The following obsolete predicates have been removed:
+* The following obsolete predicates have been removed:

      - pred `char_hash/2`
      - pred `float_hash/2`
diff --git a/compiler/hlds_goal.m b/compiler/hlds_goal.m
index b918268..5d59d70 100644
--- a/compiler/hlds_goal.m
+++ b/compiler/hlds_goal.m
@@ -465,11 +465,6 @@
              % context, and the determinism of the scope() goal itself
              % will indicate that it cannot succeed more than once.
              %
-            % This acts like the builtin.promise_only_solution predicate,
-            % but without requiring the construction of a closure, a
-            % higher order call, and the squeezing of all outputs into
-            % a single variable.
-            %
              % The promise is valid only if the list of outputs of the goal
              % inside the scope is a subset of the variables listed here.
              % If it is not valid, the compiler must emit an error message.
diff --git a/extras/curs/samples/nibbles.m b/extras/curs/samples/nibbles.m
index 21a0bbc..4fcc5d8 100644
--- a/extras/curs/samples/nibbles.m
+++ b/extras/curs/samples/nibbles.m
@@ -151,7 +151,10 @@ quit_key(27).   % escape

  :- pred direction_key(int::in, direction::out) is semidet.

-direction_key(Key, promise_only_solution(direction_key_2(Key))).
+direction_key(Key, Direction) :-
+    promise_equivalent_solutions [Direction] (
+        direction_key_2(Key, Direction)
+    ).

  :- pred direction_key_2(int::in, direction::out) is cc_nondet.

diff --git a/library/builtin.m b/library/builtin.m
index 7a8a950..73a1a8a 100644
--- a/library/builtin.m
+++ b/library/builtin.m
@@ -183,54 +183,6 @@

  %---------------------------------------------------------------------------%

-    % A call to the function `promise_only_solution(Pred)' constitutes a
-    % promise on the part of the caller that Pred has at most one
-    % solution, i.e. that `not some [X1, X2] (Pred(X1), Pred(X2), X1 \=
-    % X2)'. `promise_only_solution(Pred)' presumes that this assumption is
-    % satisfied, and returns the X for which Pred(X) is true, if there is
-    % one.
-    %
-    % You can use `promise_only_solution' as a way of introducing
-    % `cc_multi' or `cc_nondet' code inside a `det' or `semidet' procedure.
-    %
-    % Note that misuse of this function may lead to unsound results: if the
-    % assumption is not satisfied, the behaviour is undefined. (If you lie
-    % to the compiler, the compiler will get its revenge!)
-    %
-    % NOTE: This function is deprecated and will be removed in a future
-    % release. Use a `promise_equivalent_solutions' goal instead.
-    %
-:- pragma obsolete(func(promise_only_solution/1)).
-:- func promise_only_solution(pred(T)) = T.
-:- mode promise_only_solution(pred(out) is cc_multi) = out is det.
-:- mode promise_only_solution(pred(uo) is cc_multi) = uo is det.
-:- mode promise_only_solution(pred(out) is cc_nondet) = out is semidet.
-:- mode promise_only_solution(pred(uo) is cc_nondet) = uo is semidet.
-
-    % `promise_only_solution_io' is like `promise_only_solution', but for
-    % procedures with unique modes (e.g. those that do IO).
-    %
-    % A call to `promise_only_solution_io(P, X, IO0, IO)' constitutes a
-    % promise on the part of the caller that for the given IO0, there is
-    % only one value of X and IO for which `P(X, IO0, IO)' is true.
-    % `promise_only_solution_io(P, X, IO0, IO)' presumes that this
-    % assumption is satisfied, and returns the X and IO for which
-    % `P(X, IO0, IO)' is true.
-    %
-    % Note that misuse of this predicate may lead to unsound results: if
-    % the assumption is not satisfied, the behaviour is undefined. (If you
-    % lie to the compiler, the compiler will get its revenge!)
-    %
-    % NOTE: This predicate is deprecated and will be removed in a future
-    % release. Use a `promise_equivalent_solutions' goal instead.
-    %
-:- pragma obsolete(pred(promise_only_solution_io/4)).
-:- pred promise_only_solution_io(
-    pred(T, IO, IO)::in(pred(out, di, uo) is cc_multi), T::out,
-    IO::di, IO::uo) is det.
-
-%---------------------------------------------------------------------------%
-
      % unify(X, Y) is true iff X = Y.
      %
  :- pred unify(T::in, T::in) is semidet.
@@ -433,22 +385,6 @@
  :- pred compare_representation(comparison_result, T, T).
  :- mode compare_representation(uo, in, in) is cc_multi.

-    % `get_one_solution' and `get_one_solution_io' are impure alternatives
-    % to `promise_one_solution' and `promise_one_solution_io', respectively.
-    % They get a solution to the procedure, without requiring any promise
-    % that there is only one solution. However, they can only be used in
-    % impure code.
-    %
-:- pragma obsolete(func(get_one_solution/1)).
-:- impure func get_one_solution(pred(T)) = T.
-:-        mode get_one_solution(pred(out) is cc_multi) = out is det.
-:-        mode get_one_solution(pred(out) is cc_nondet) = out is semidet.
-
-:- pragma obsolete(pred(get_one_solution_io/4)).
-:- impure pred get_one_solution_io(pred(T, IO, IO), T, IO, IO).
-:-        mode get_one_solution_io(pred(out, di, uo) is cc_multi,
-        out, di, uo) is det.
-
      % Set up Mercury runtime to call special predicates implemented in this
      % module.
      %
@@ -471,26 +407,6 @@ false :-

  %---------------------------------------------------------------------------%

-    % XXX The calls to unsafe_promise_unique below work around
-    % mode checker limitations.
-:- pragma promise_pure(func(promise_only_solution/1)).
-promise_only_solution(CCPred::(pred(out) is cc_multi)) = (OutVal::out) :-
-    impure OutVal = get_one_solution(CCPred).
-promise_only_solution(CCPred::(pred(uo) is cc_multi)) = (OutVal::uo) :-
-    impure OutVal0 = get_one_solution(CCPred),
-    OutVal = unsafe_promise_unique(OutVal0).
-promise_only_solution(CCPred::(pred(out) is cc_nondet)) = (OutVal::out) :-
-    impure OutVal = get_one_solution(CCPred).
-promise_only_solution(CCPred::(pred(uo) is cc_nondet)) = (OutVal::uo) :-
-    impure OutVal0 = get_one_solution(CCPred),
-    OutVal = unsafe_promise_unique(OutVal0).
-
-:- pragma promise_pure(pred(promise_only_solution_io/4)).
-promise_only_solution_io(Pred, X, !IO) :-
-    impure get_one_solution_io(Pred, X, !IO).
-
-%---------------------------------------------------------------------------%
-
  % IMPORTANT: any changes or additions to external predicates should be
  % reflected in the definition of pred_is_external in
  % mdbcomp/program_representation.m. The debugger needs to know what predicates
@@ -1295,20 +1211,6 @@ dynamic_cast(X, Y) :-

  %---------------------------------------------------------------------------%

-get_one_solution(CCPred) = OutVal :-
-    promise_equivalent_solutions [OutVal] (
-        CCPred(OutVal),
-        impure impure_true
-    ).
-
-get_one_solution_io(Pred, X, !IO) :-
-    promise_equivalent_solutions [!:IO, X] (
-        Pred(X, !IO),
-        impure impure_true
-    ).
-
-%---------------------------------------------------------------------------%
-
  init_runtime_hooks.

  :- pragma foreign_proc("C",
diff --git a/tests/declarative_debugger/exceptions.m b/tests/declarative_debugger/exceptions.m
index ce78d04..1badeaa 100644
--- a/tests/declarative_debugger/exceptions.m
+++ b/tests/declarative_debugger/exceptions.m
@@ -59,7 +59,9 @@ q(MaybeExcp, Solutions) :-
  r(Sols) :-
      % This is a lie, but is the only way I seem to be able to call try_all
      % in a failing context.
-    Sols = promise_only_solution(t),
+    promise_equivalent_solutions [Sols] (
+        t(Sols)
+    ),
      semidet_fail.

  :- pred s(int::out) is multi.
diff --git a/tests/declarative_debugger/trust.exp b/tests/declarative_debugger/trust.exp
index 681f64f..4851d18 100644
--- a/tests/declarative_debugger/trust.exp
+++ b/tests/declarative_debugger/trust.exp
@@ -3,23 +3,12 @@ mdb> mdb> mdb> Contexts will not be printed.
  mdb> echo on
  Command echo enabled.
  mdb> trust trust_1.
-Ambiguous predicate or function specification. The matches are:
-0: pred trust_1.w_cmp/3
-1: pred trust_1.lambda_trust_1_m_21/3
-
-Which predicate or function do you want to trust (0-1 or *)? *
  Trusting pred trust_1.w_cmp/3
-Trusting pred trust_1.lambda_trust_1_m_21/3
  mdb> trusted
  Trusted Objects:
  1: predicate trust_1.w_cmp/3
-2: predicate trust_1.lambda_trust_1_m_21/3
  mdb> untrust 1
  mdb> trusted
-Trusted Objects:
-2: predicate trust_1.lambda_trust_1_m_21/3
-mdb> untrust 2
-mdb> trusted
  There are no trusted modules, predicates or functions.
  mdb> trust trust_2
  Trusting module trust_2
@@ -32,15 +21,15 @@ Which predicate or function do you want to trust (0-1 or *)? 0
  Trusting pred trust.main/2
  mdb> trusted
  Trusted Objects:
-3: module trust_2
-4: predicate trust.main/2
+2: module trust_2
+3: predicate trust.main/2
  mdb> trust trust_2
  Trusting module trust_2
  mdb> trusted
  Trusted Objects:
-3: module trust_2
-4: predicate trust.main/2
-mdb> untrust 3
+2: module trust_2
+3: predicate trust.main/2
+mdb> untrust 2
  mdb> trust trust_1
  Trusting module trust_1
  mdb> trust no_such_module
@@ -53,22 +42,22 @@ mdb> trust standard library
  Trusting the Mercury standard library
  mdb> trusted
  Trusted Objects:
-4: predicate trust.main/2
-5: module trust_1
-6: predicate trust_2.concat/3
-7: the Mercury standard library
-mdb> untrust 4
+3: predicate trust.main/2
+4: module trust_1
+5: predicate trust_2.concat/3
+6: the Mercury standard library
+mdb> untrust 3
  mdb> trusted
  Trusted Objects:
-5: module trust_1
-6: predicate trust_2.concat/3
-7: the Mercury standard library
-mdb> untrust 4
+4: module trust_1
+5: predicate trust_2.concat/3
+6: the Mercury standard library
+mdb> untrust 3
  mdb: no such trusted object
  mdb> untrust 99
  mdb: no such trusted object
+mdb> untrust 4
  mdb> untrust 5
-mdb> untrust 6
  mdb> step
        E2:     C2 CALL pred trust.dostuff/2-0 (cc_multi)
  mdb> finish
@@ -80,8 +69,6 @@ w_cmp('=', w("aaB"), w("aAB"))
  Valid? trust
  concat(w("aaa"), w("bbb"), w("aaabbb"))
  Valid? trust module
-lambda_trust_1_m_21(w("aaB"), w("aAB"), '=')
-Valid? trust module
  Found incorrect contour:
  w_cmp('=', w("aaB"), w("aAB"))
  concat(w("aaa"), w("bbb"), w("aaabbb"))
diff --git a/tests/declarative_debugger/trust.inp b/tests/declarative_debugger/trust.inp
index df8972d..2d6e0e2 100644
--- a/tests/declarative_debugger/trust.inp
+++ b/tests/declarative_debugger/trust.inp
@@ -3,37 +3,33 @@ untrust 0
  context none
  echo on
  trust trust_1.
-*
  trusted
  untrust 1
  trusted
-untrust 2
-trusted
  trust trust_2
  trust trust.
  0
  trusted
  trust trust_2
  trusted
-untrust 3
+untrust 2
  trust trust_1
  trust no_such_module
  trust trust_2.
  trust std lib
  trust standard library
  trusted
-untrust 4
+untrust 3
  trusted
-untrust 4
+untrust 3
  untrust 99
+untrust 4
  untrust 5
-untrust 6
  step
  finish
  dd -d 3 -n 7
  n
  trust
  trust module
-trust module
  y
  continue
diff --git a/tests/declarative_debugger/trust_1.m b/tests/declarative_debugger/trust_1.m
index 63c429e..0974b6d 100644
--- a/tests/declarative_debugger/trust_1.m
+++ b/tests/declarative_debugger/trust_1.m
@@ -17,14 +17,9 @@
  :- implementation.

  w_cmp(R, W1, W2) :-
-    R = unsafe_promise_unique(
-        promise_only_solution(
-            ( pred(R1::out) is cc_multi :-
-                W1 = w(S1),
-                W2 = w(S2),
-                compare(R1, to_upper(S1)`with_type`string,
-                    to_upper(S2))
-            )
-        )
-    ).
-
+    promise_equivalent_solutions [R1] (
+        W1 = w(S1),
+        W2 = w(S2),
+        compare(R1, to_upper(S1) : string, to_upper(S2))
+    ),
+    R = unsafe_promise_unique(R1).
diff --git a/tests/hard_coded/myset.m b/tests/hard_coded/myset.m
index 596c886..3ee63ce 100644
--- a/tests/hard_coded/myset.m
+++ b/tests/hard_coded/myset.m
@@ -52,12 +52,10 @@ set(List) = set_rep(List).

  set_to_list(set_rep(List), List).

-set_to_sorted_list(Set) =
-    promise_only_solution(
-        ( pred(Sorted::out) is cc_multi :-
-            Set = set_rep(Unsorted),
-            list.sort(Unsorted, Sorted)
-        )
+set_to_sorted_list(Set) = Sorted :-
+    promise_equivalent_solutions [Sorted] (
+        Set = set_rep(Unsorted),
+        list.sort(Unsorted, Sorted)
      ).

  {} = set_rep([]).
@@ -65,21 +63,18 @@ set_to_sorted_list(Set) =
  {X} = set_rep([X]).

  is_empty(Set) :-
-    promise_only_solution(
-        ( pred(Empty::out) is cc_multi :-
-            Set = set_rep(List),
-            Empty = (if List = [] then yes else no)
-        )
-    ) = yes.
-
-Set1 + Set2 =
-    promise_only_solution(
-        ( pred(Union::out) is cc_multi :-
-            Set1 = set_rep(List1),
-            Set2 = set_rep(List2),
-            list.append(List1, List2, UnionList),
-            Union = set_rep(UnionList)
-        )
+    promise_equivalent_solutions [Empty] (
+        Set = set_rep(List),
+        Empty = (if List = [] then yes else no)
+    ),
+    Empty = yes.
+
+Set1 + Set2 = Union :-
+    promise_equivalent_solutions [Union] (
+        Set1 = set_rep(List1),
+        Set2 = set_rep(List2),
+        list.append(List1, List2, UnionList),
+        Union = set_rep(UnionList)
      ).

  % [Element | set_rep(Rest)] = set_rep([Element | Rest]).
diff --git a/tests/hard_coded/user_compare.m b/tests/hard_coded/user_compare.m
index fc09718..961f7b4 100644
--- a/tests/hard_coded/user_compare.m
+++ b/tests/hard_coded/user_compare.m
@@ -43,14 +43,11 @@ main(!IO) :-
  :- pred compare_foo(comparison_result::uo, foo::in, foo::in) is det.

  compare_foo(Res, Foo1, Foo2) :-
-    Res1 = promise_only_solution(
-        (pred(Res0::uo) is cc_multi :-
-                Foo1 = foo(Int1),
-                Foo2 = foo(Int2),
-                compare(Res0, Int2, Int1)
-        )
-    ),
-    Res = Res1.
+    promise_equivalent_solutions [Res] (
+        Foo1 = foo(Int1),
+        Foo2 = foo(Int2),
+        compare(Res, Int2, Int1)
+    ).

  :- type foreign.
  :- pragma foreign_type(c, foreign, "int") where
diff --git a/tests/valid_seq/intermod_nested_module_bug2.m b/tests/valid_seq/intermod_nested_module_bug2.m
index c883115..1138fc6 100644
--- a/tests/valid_seq/intermod_nested_module_bug2.m
+++ b/tests/valid_seq/intermod_nested_module_bug2.m
@@ -21,7 +21,9 @@
  :- implementation.

  get_request(Res, !IO) :-
-    Res = promise_only_solution(get_request0).
+    promise_equivalent_solutions [Res] (
+        get_request0(Res)
+    ).

  :- pred get_request0(maybe_error(cgi)::out) is cc_multi.



More information about the reviews mailing list