[m-rev.] for review: Do not opt-export `try' goals.

Peter Wang novalazy at gmail.com
Mon Sep 19 13:37:09 AEST 2016


This fixes a serious issue as `try' goals are not properly written to
.opt files, so when read back would not actually catch any exceptions.
Bug #420.

At the point where we are to create the .opt file, the pieces of a `try'
goal exist in a "pre-transformed" hlds_goal. Teasing apart the pieces to
resemble the original `try' goal would be non-trivial.

compiler/intermod.m:
        Do not export any predicate or function with a clause containing a
        `try' goal.

library/exception.m
	Throw an exception if the dummy predicate
	`magic_exception_result/1' is ever called.

tests/hard_coded/Mercury.options:
tests/hard_coded/Mmakefile:
tests/hard_coded/intermod_try_goal.exp:
tests/hard_coded/intermod_try_goal.m:
tests/hard_coded/intermod_try_goal2.m:
	Add test case.

NEWS:
	Announce change.
---
 NEWS                                   |  5 +++++
 compiler/intermod.m                    |  8 ++++----
 library/exception.m                    |  4 ++--
 tests/hard_coded/Mercury.options       |  2 ++
 tests/hard_coded/Mmakefile             |  1 +
 tests/hard_coded/intermod_try_goal.exp |  2 ++
 tests/hard_coded/intermod_try_goal.m   | 29 +++++++++++++++++++++++++++++
 tests/hard_coded/intermod_try_goal2.m  | 30 ++++++++++++++++++++++++++++++
 8 files changed, 75 insertions(+), 6 deletions(-)
 create mode 100644 tests/hard_coded/intermod_try_goal.exp
 create mode 100644 tests/hard_coded/intermod_try_goal.m
 create mode 100644 tests/hard_coded/intermod_try_goal2.m

diff --git a/NEWS b/NEWS
index 10c4b89..ef18920 100644
--- a/NEWS
+++ b/NEWS
@@ -443,6 +443,11 @@ Changes to the Mercury compiler:
   prevent the compiler adding any directories to the runtime search path
   automatically.
 
+* We have disabled intermodule optimisation of any predicates or functions
+  using `try' goals. This fixes a serious issue as `try' goals are not
+  properly written to .opt files, so when read back would not actually
+  catch any exceptions.
+
 Change to the Mercury debugger:
 
 * Interactive queries are now supported on OS X.
diff --git a/compiler/intermod.m b/compiler/intermod.m
index 0ae6cae..f7bfe84 100644
--- a/compiler/intermod.m
+++ b/compiler/intermod.m
@@ -697,10 +697,10 @@ gather_entities_to_opt_export_in_goal_expr(GoalExpr0, GoalExpr,
             ShortHand = atomic_goal(GoalType, Outer, Inner, MaybeOutputVars,
                 MainGoal, OrElseGoals, OrElseInners)
         ;
-            ShortHand0 = try_goal(MaybeIO, ResultVar, SubGoal0),
-            gather_entities_to_opt_export_in_goal(SubGoal0, SubGoal,
-                DoWrite, !IntermodInfo),
-            ShortHand = try_goal(MaybeIO, ResultVar, SubGoal)
+            ShortHand0 = try_goal(_MaybeIO, _ResultVar, _SubGoal0),
+            % hlds_out_goal.m does not write out `try' goals properly.
+            DoWrite = no,
+            ShortHand = ShortHand0
         ;
             ShortHand0 = bi_implication(_, _),
             % These should have been expanded out by now.
diff --git a/library/exception.m b/library/exception.m
index 2f133b9..ed99dda 100644
--- a/library/exception.m
+++ b/library/exception.m
@@ -616,8 +616,8 @@ unsafe_call_transaction_goal(Goal, STM0, {Result, STM}) :-
 
 %---------------------------------------------------------------------------%
 
-magic_exception_result(succeeded({})).
-magic_exception_result(succeeded({})).  % force cc_multi
+magic_exception_result(_) :-
+    throw("magic_exception_result called").
 
 unreachable :-
     throw("unreachable code reached").
diff --git a/tests/hard_coded/Mercury.options b/tests/hard_coded/Mercury.options
index d375801..da88e2a 100644
--- a/tests/hard_coded/Mercury.options
+++ b/tests/hard_coded/Mercury.options
@@ -45,6 +45,8 @@ MCFLAGS-intermod_poly_mode = 	--intermodule-optimization
 MCFLAGS-intermod_poly_mode_2 = 	--intermodule-optimization
 MCFLAGS-intermod_pragma_clause = --intermodule-optimization
 MCFLAGS-intermod_pragma_clause_sub = --intermodule-optimization
+MCFLAGS-intermod_try_goal =	--intermodule-optimization
+MCFLAGS-intermod_try_goal2 =	--intermodule-optimization
 MCFLAGS-intermod_type_qual =	--intermodule-optimization
 MCFLAGS-intermod_type_qual2 =	--intermodule-optimization
 MCFLAGS-intermod_multimode =	--intermodule-optimization
diff --git a/tests/hard_coded/Mmakefile b/tests/hard_coded/Mmakefile
index d2dc634..2c2e75a 100644
--- a/tests/hard_coded/Mmakefile
+++ b/tests/hard_coded/Mmakefile
@@ -171,6 +171,7 @@ ORDINARY_PROGS =	\
 	intermod_multimode_main \
 	intermod_poly_mode \
 	intermod_pragma_clause \
+	intermod_try_goal \
 	intermod_type_qual \
 	intermod_unused_args \
 	java_rtti_bug \
diff --git a/tests/hard_coded/intermod_try_goal.exp b/tests/hard_coded/intermod_try_goal.exp
new file mode 100644
index 0000000..b636aa5
--- /dev/null
+++ b/tests/hard_coded/intermod_try_goal.exp
@@ -0,0 +1,2 @@
+caught exception: "catch me"
+done.
diff --git a/tests/hard_coded/intermod_try_goal.m b/tests/hard_coded/intermod_try_goal.m
new file mode 100644
index 0000000..dd8db3e
--- /dev/null
+++ b/tests/hard_coded/intermod_try_goal.m
@@ -0,0 +1,29 @@
+%---------------------------------------------------------------------------%
+% vim: ts=4 sw=4 et ft=mercury
+%---------------------------------------------------------------------------%
+
+:- module intermod_try_goal.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is cc_multi.
+
+:- implementation.
+
+:- import_module exception.
+
+:- import_module intermod_try_goal2.
+
+main(!IO) :-
+    catcher(thrower, !IO),
+    io.write_string("done.\n", !IO).
+
+:- pred thrower(io::di, io::uo) is det.
+
+thrower(!IO) :-
+    ( if semidet_true then
+        throw("catch me")
+    else
+        true
+    ).
diff --git a/tests/hard_coded/intermod_try_goal2.m b/tests/hard_coded/intermod_try_goal2.m
new file mode 100644
index 0000000..88fea0d
--- /dev/null
+++ b/tests/hard_coded/intermod_try_goal2.m
@@ -0,0 +1,30 @@
+%---------------------------------------------------------------------------%
+% vim: ts=4 sw=4 et ft=mercury
+%---------------------------------------------------------------------------%
+
+:- module intermod_try_goal2.
+:- interface.
+
+:- import_module io.
+
+:- pred catcher(pred(io, io), io, io).
+:- mode catcher(pred(di, uo) is det, di, uo) is cc_multi.
+
+:- implementation.
+
+:- import_module string.
+
+    % intermod.m must ignore this pragma until `try' goals can be written
+    % properly to .opt files.
+    %
+:- pragma inline(catcher/3).
+
+catcher(Pred, !IO) :-
+    ( try [io(!IO)]
+        Pred(!IO)
+    then
+        true
+    catch_any Excp ->
+        io.write_string("caught exception: " ++ string(Excp), !IO),
+        io.nl(!IO)
+    ).
-- 
2.9.0



More information about the reviews mailing list