[m-rev.] preliminary review: Fix lax matching of ground inst with bound final inst.

Peter Wang novalazy at gmail.com
Mon Aug 18 16:06:37 AEST 2014


The mode checker contains a hack whereby matching a ground inst to a
bound final inst will succeed even if the bound inst does not cover all
the functors of the type, or if the type is unknown.  The stated reason
is that otherwise the mode checker is too conservative in the absence of
alias tracking.  I think this runs counter to the typical behaviour
expected of the compiler.

This change removes the hack, thus rejecting more mode-incorrect code,
but also rejecting some mode-correct code.

Some compiler-generated unify predicates are among those that would be
rejected.  We apply the lax inst matching to them as a special case,
which is no worse than before.

XXX contravariance_poly is broken but that may be due to a weakness
elsewhere

compiler/hlds_pred.m:
	Add helper predicate `is_unify_pred'.

compiler/inst_match.m:
	Remove the lax final inst matching in `inst_matches_final_3'.

	Add a variant of `inst_matches_final_typed' to enable the old
	behaviour.

	Remove a similar hack in `inst_matches_binding_3'.  I have not
	yet come across a case where the old behaviour was required.

compiler/modes.m:
	Use the lax inst matching behaviour for checking the final insts
	of compiler-generated unify predicates only.

compiler/instmap.m:
	Add `instmap_changed_vars_old' to emulate the old behavior of
	`instmap_changed_vars', which has been affected.

compiler/prog_rep.m:
	Use `instmap_changed_vars_old' in a spot to avoid breaking some
	declarative debugging test cases.  I don't know where the real
	problem lies.

NEWS:
	Announce change.
---
 NEWS                  |   5 +++
 compiler/hlds_pred.m  |   9 +++++
 compiler/inst_match.m |  71 ++++++++++++++++++++++-------------
 compiler/instmap.m    |  29 ++++++++++++---
 compiler/modes.m      | 100 +++++++++++++++++++++++++++++---------------------
 compiler/prog_rep.m   |   2 +-
 6 files changed, 143 insertions(+), 73 deletions(-)

diff --git a/NEWS b/NEWS
index ff33f20..8ba26c1 100644
--- a/NEWS
+++ b/NEWS
@@ -37,6 +37,11 @@ Changes to the Mercury standard library:
 
 Changes to the Mercury compiler:
 
+* We have enabled stricter checking of non-ground final insts, rejecting more
+  mode-incorrect code.  However, due to compiler limitations, some code which
+  should be accepted will now be rejected, and will require modifications to
+  appease the compiler.
+
 * We have fixed a long-standing bug causing crashes in deep profiling
   grades, related to unify/compare for tuples.  (Bug #3)
 
diff --git a/compiler/hlds_pred.m b/compiler/hlds_pred.m
index c892eef..01bad5c 100644
--- a/compiler/hlds_pred.m
+++ b/compiler/hlds_pred.m
@@ -3347,6 +3347,11 @@ pred_info_is_field_access_function(ModuleInfo, PredInfo) :-
 
 :- interface.
 
+    % is_unify_pred(PredInfo) succeeds iff the PredInfo is for a
+    % compiler-generated instance of a type-specific unify predicate.
+    %
+:- pred is_unify_pred(pred_info::in) is semidet.
+
     % is_unify_or_compare_pred(PredInfo) succeeds iff the PredInfo is for a
     % compiler generated instance of a type-specific special_pred (i.e. one
     % of the unify, compare, or index predicates generated as a type-specific
@@ -3371,6 +3376,10 @@ pred_info_is_field_access_function(ModuleInfo, PredInfo) :-
 
 :- implementation.
 
+is_unify_pred(PredInfo) :-
+    pred_info_get_origin(PredInfo, origin_special_pred(SpecialPred)),
+    SpecialPred = spec_pred_unify - _TypeCtor.
+
 is_unify_or_compare_pred(PredInfo) :-
     pred_info_get_origin(PredInfo, origin_special_pred(_)). % XXX bug
 
diff --git a/compiler/inst_match.m b/compiler/inst_match.m
index 4225954..c475ce5 100644
--- a/compiler/inst_match.m
+++ b/compiler/inst_match.m
@@ -117,6 +117,17 @@
 :- pred inst_matches_final_typed(mer_inst::in, mer_inst::in, mer_type::in,
     module_info::in) is semidet.
 
+:- type trust_final_insts
+    --->    trust_final_insts
+    ;       do_not_trust_final_insts.
+
+    % This version of inst_matches_final_typed is a hack to accept some
+    % compiler-generated predicates that the mode checker would reject
+    % due to the absence of alias tracking.
+    %
+:- pred inst_matches_final_typed(mer_inst::in, mer_inst::in, mer_type::in,
+    module_info::in, trust_final_insts::in) is semidet.
+
     % The difference between inst_matches_initial and inst_matches_final is
     % that inst_matches_initial requires only something which is at least as
     % instantiated, whereas this predicate wants something which is an exact
@@ -408,7 +419,8 @@ inst_expand_and_remove_constrained_inst_vars(ModuleInfo, !Inst) :-
                 imi_maybe_sub               :: maybe(inst_var_sub),
                 imi_calculate_sub           :: calculate_sub,
                 imi_uniqueness_comparison   :: uniqueness_comparison,
-                imi_any_matches_any         :: bool
+                imi_any_matches_any         :: bool,
+                imi_trust_final_insts       :: trust_final_insts
             ).
 
     % The calculate_sub type determines how the inst var substitution
@@ -428,12 +440,13 @@ inst_expand_and_remove_constrained_inst_vars(ModuleInfo, !Inst) :-
             % Do not calculate inst var substitions.
 
 :- func init_inst_match_info(module_info, maybe(inst_var_sub),
-    calculate_sub, uniqueness_comparison, bool) = inst_match_info.
+    calculate_sub, uniqueness_comparison, bool, trust_final_insts) =
+    inst_match_info.
 
 init_inst_match_info(ModuleInfo, MaybeSub, CalculateSub, Comparison,
-        AnyMatchesAny) =
+        AnyMatchesAny, TrustFinalInsts) =
     inst_match_info(ModuleInfo, expansion_init, MaybeSub, CalculateSub,
-        Comparison, AnyMatchesAny).
+        Comparison, AnyMatchesAny, TrustFinalInsts).
 
 :- type inst_matches_pred ==
     pred(mer_inst, mer_inst, maybe(mer_type),
@@ -572,13 +585,14 @@ inst_matches_initial_sub(InstA, InstB, Type, !ModuleInfo, !Sub) :-
     ).
 
 inst_matches_initial_no_implied_modes(InstA, InstB, Type, ModuleInfo) :-
-    Info0 = init_inst_match_info(ModuleInfo, no, cs_forward, uc_match, yes),
+    Info0 = init_inst_match_info(ModuleInfo, no, cs_forward, uc_match, yes,
+        do_not_trust_final_insts),
     inst_matches_final_mt(InstA, InstB, yes(Type), Info0, _).
 
 inst_matches_initial_no_implied_modes_sub(InstA, InstB, Type, !ModuleInfo,
         !Sub) :-
     Info0 = init_inst_match_info(!.ModuleInfo, yes(!.Sub), cs_forward,
-        uc_match, yes),
+        uc_match, yes, do_not_trust_final_insts),
     inst_matches_final_mt(InstA, InstB, yes(Type), Info0, Info),
     !:ModuleInfo = Info ^ imi_module_info,
     yes(!:Sub) = Info ^ imi_maybe_sub.
@@ -589,7 +603,7 @@ inst_matches_initial_no_implied_modes_sub(InstA, InstB, Type, !ModuleInfo,
 
 inst_matches_initial_1(InstA, InstB, Type, !ModuleInfo, !MaybeSub) :-
     Info0 = init_inst_match_info(!.ModuleInfo, !.MaybeSub, cs_forward,
-        uc_match, yes),
+        uc_match, yes, do_not_trust_final_insts),
     inst_matches_initial_mt(InstA, InstB, yes(Type), Info0, Info),
     !:ModuleInfo = Info ^ imi_module_info,
     !:MaybeSub = Info ^ imi_maybe_sub.
@@ -880,7 +894,8 @@ pred_inst_matches(PredInstA, PredInstB, ModuleInfo) :-
     maybe(mer_type)::in, module_info::in) is semidet.
 
 pred_inst_matches_mt(PredInstA, PredInstB, MaybeType, ModuleInfo) :-
-    Info0 = init_inst_match_info(ModuleInfo, no, cs_none, uc_match, yes),
+    Info0 = init_inst_match_info(ModuleInfo, no, cs_none, uc_match, yes,
+        do_not_trust_final_insts),
     pred_inst_matches_2(PredInstA, PredInstB, MaybeType, Info0, _).
 
     % pred_inst_matches_2(PredInstA, PredInstB, !Info)
@@ -1036,11 +1051,17 @@ inst_list_matches_initial_mt([X | Xs], [Y | Ys], [MaybeType | MaybeTypes],
 %-----------------------------------------------------------------------------%
 
 inst_matches_final(InstA, InstB, ModuleInfo) :-
-    Info0 = init_inst_match_info(ModuleInfo, no, cs_none, uc_match, yes),
+    Info0 = init_inst_match_info(ModuleInfo, no, cs_none, uc_match, yes,
+        do_not_trust_final_insts),
     inst_matches_final_mt(InstA, InstB, no, Info0, _).
 
 inst_matches_final_typed(InstA, InstB, Type, ModuleInfo) :-
-    Info0 = init_inst_match_info(ModuleInfo, no, cs_none, uc_match, yes),
+    inst_matches_final_typed(InstA, InstB, Type, ModuleInfo,
+        do_not_trust_final_insts).
+
+inst_matches_final_typed(InstA, InstB, Type, ModuleInfo, TrustFinalInsts) :-
+    Info0 = init_inst_match_info(ModuleInfo, no, cs_none, uc_match, yes,
+        TrustFinalInsts),
     inst_matches_final_mt(InstA, InstB, yes(Type), Info0, _).
 
 :- pred inst_matches_final_mt(mer_inst::in, mer_inst::in, maybe(mer_type)::in,
@@ -1138,14 +1159,12 @@ inst_matches_final_3(InstA, InstB, MaybeType, !Info) :-
             MaybeType = yes(Type),
             % We can only do this check if the type is known.
             bound_inst_list_is_complete_for_type(set.init, ModuleInfo,
-            BoundInstsB,
-                Type)
+                BoundInstsB, Type)
         ;
-            true
-            % XXX enabling the check for bound_inst_list_is_complete
-            % for type makes the mode checker too conservative in
-            % the absence of alias tracking, so we currently always
-            % succeed, even if this check fails.
+            % XXX the check for bound_inst_list_is_complete_for_type makes the
+            % mode checker too conservative in the absence of alias tracking.
+            % Assume there is no error, when instructed.
+            !.Info ^ imi_trust_final_insts = trust_final_insts
         )
     ;
         InstA = ground(UniqA, HOInstInfoA),
@@ -1236,15 +1255,18 @@ bound_inst_list_matches_final([X | Xs], [Y | Ys], MaybeType, !Info) :-
     ).
 
 inst_is_at_least_as_instantiated(InstA, InstB, Type, ModuleInfo) :-
-    Info0 = init_inst_match_info(ModuleInfo, no, cs_none, uc_instantiated, no),
+    Info0 = init_inst_match_info(ModuleInfo, no, cs_none, uc_instantiated, no,
+        do_not_trust_final_insts),
     inst_matches_initial_mt(InstA, InstB, yes(Type), Info0, _).
 
 inst_matches_binding(InstA, InstB, Type, ModuleInfo) :-
-    Info0 = init_inst_match_info(ModuleInfo, no, cs_none, uc_match, no),
+    Info0 = init_inst_match_info(ModuleInfo, no, cs_none, uc_match, no,
+        do_not_trust_final_insts),
     inst_matches_binding_mt(InstA, InstB, yes(Type), Info0, _).
 
 inst_matches_binding_allow_any_any(InstA, InstB, Type, ModuleInfo) :-
-    Info0 = init_inst_match_info(ModuleInfo, no, cs_none, uc_match, yes),
+    Info0 = init_inst_match_info(ModuleInfo, no, cs_none, uc_match, yes,
+        do_not_trust_final_insts),
     inst_matches_binding_mt(InstA, InstB, yes(Type), Info0, _).
 
 :- pred inst_matches_binding_mt(mer_inst::in, mer_inst::in,
@@ -1335,11 +1357,10 @@ inst_matches_binding_3(InstA, InstB, MaybeType, !Info) :-
             bound_inst_list_is_complete_for_type(set.init,
                 !.Info ^ imi_module_info, BoundInstsB, Type)
         ;
-            true
-            % XXX Enabling the check for bound_inst_list_is_complete
-            % for type makes the mode checker too conservative in
-            % the absence of alias tracking, so we currently always
-            % succeed, even if this check fails.
+            % XXX We used to always succeed despite
+            % bound_inst_list_is_complete_for_type failing as in
+            % inst_matches_final_3.
+            fail
         )
     ;
         InstA = ground(_UniqA, HOInstInfoA),
diff --git a/compiler/instmap.m b/compiler/instmap.m
index 13e94eb..7b72235 100644
--- a/compiler/instmap.m
+++ b/compiler/instmap.m
@@ -121,6 +121,13 @@
 :- pred instmap_changed_vars(instmap::in, instmap::in, vartypes::in,
     module_info::in, set_of_progvar::out) is det.
 
+    % The old behaviour of instmap_changed_vars.
+    % This should only be used by goal_info_to_atomic_goal_rep_fields
+    % until the real problem is found.
+    %
+:- pred instmap_changed_vars_old(instmap::in, instmap::in, vartypes::in,
+    module_info::in, set_of_progvar::out) is det.
+
 %-----------------------------------------------------------------------------%
 
     % Given an instmap and a variable, determine the inst of that variable.
@@ -501,24 +508,34 @@ instmap_delta_changed_vars(reachable(InstMapping), ChangedVars) :-
 instmap_changed_vars(InstMapA, InstMapB, VarTypes, ModuleInfo, ChangedVars) :-
     instmap_vars_list(InstMapB, VarsB),
     instmap_changed_vars_2(VarsB, InstMapA, InstMapB, VarTypes, ModuleInfo,
-        ChangedVars).
+        do_not_trust_final_insts, ChangedVars).
+
+instmap_changed_vars_old(InstMapA, InstMapB, VarTypes, ModuleInfo, ChangedVars)
+        :-
+    instmap_vars_list(InstMapB, VarsB),
+    instmap_changed_vars_2(VarsB, InstMapA, InstMapB, VarTypes, ModuleInfo,
+        trust_final_insts, ChangedVars).
 
 :- pred instmap_changed_vars_2(prog_vars::in, instmap::in, instmap::in,
-    vartypes::in, module_info::in, set_of_progvar::out) is det.
+    vartypes::in, module_info::in, trust_final_insts::in, set_of_progvar::out)
+    is det.
 
 instmap_changed_vars_2([], _InstMapA, _InstMapB, _Types,
-        _ModuleInfo, ChangedVars) :-
+        _ModuleInfo, _TrustFinalInsts, ChangedVars) :-
     set_of_var.init(ChangedVars).
 instmap_changed_vars_2([VarB | VarBs], InstMapA, InstMapB, VarTypes,
-        ModuleInfo, ChangedVars) :-
+        ModuleInfo, TrustFinalInsts, ChangedVars) :-
     instmap_changed_vars_2(VarBs, InstMapA, InstMapB, VarTypes,
-        ModuleInfo, ChangedVars0),
+        ModuleInfo, TrustFinalInsts, ChangedVars0),
 
     instmap_lookup_var(InstMapA, VarB, InitialInst),
     instmap_lookup_var(InstMapB, VarB, FinalInst),
     lookup_var_type(VarTypes, VarB, Type),
 
-    ( inst_matches_final_typed(InitialInst, FinalInst, Type, ModuleInfo) ->
+    (
+        inst_matches_final_typed(InitialInst, FinalInst, Type, ModuleInfo,
+            TrustFinalInsts)
+    ->
         ChangedVars = ChangedVars0
     ;
         set_of_var.insert(VarB, ChangedVars0, ChangedVars)
diff --git a/compiler/modes.m b/compiler/modes.m
index c8803cc..1a12772 100644
--- a/compiler/modes.m
+++ b/compiler/modes.m
@@ -636,11 +636,18 @@ do_modecheck_proc(ProcId, PredId, WhatToCheck, MayChangeCalledProc,
         ;
             InferModes = no
         ),
+        ( is_unify_pred(PredInfo) ->
+            % The mode checker is currently unable to verify the final insts of
+            % some compiler-generated unify predicates.
+            TrustFinalInsts = trust_final_insts
+        ;
+            TrustFinalInsts = do_not_trust_final_insts
+        ),
         mode_list_get_final_insts(!.ModuleInfo, ArgModes0, ArgFinalInsts0),
 
         modecheck_proc_body(!.ModuleInfo, WhatToCheck, InferModes,
-            Markers, PredId, ProcId, Body0, Body, HeadVars, InstMap0,
-            ArgFinalInsts0, ArgFinalInsts, !ModeInfo),
+            TrustFinalInsts, Markers, PredId, ProcId, Body0, Body, HeadVars,
+            InstMap0, ArgFinalInsts0, ArgFinalInsts, !ModeInfo),
 
         mode_info_get_errors(!.ModeInfo, ModeErrors),
         (
@@ -700,17 +707,17 @@ do_modecheck_proc(ProcId, PredId, WhatToCheck, MayChangeCalledProc,
     ).
 
 :- pred modecheck_proc_body(module_info::in, how_to_check_goal::in,
-    bool::in, pred_markers::in, pred_id::in, proc_id::in,
-    hlds_goal::in, hlds_goal::out,
+    bool::in, trust_final_insts::in, pred_markers::in,
+    pred_id::in, proc_id::in, hlds_goal::in, hlds_goal::out,
     list(prog_var)::in, instmap::in, list(mer_inst)::in, list(mer_inst)::out,
     mode_info::in, mode_info::out) is det.
 
-modecheck_proc_body(ModuleInfo, WhatToCheck, InferModes, Markers,
-        PredId, ProcId, Body0, Body, HeadVars, InstMap0,
+modecheck_proc_body(ModuleInfo, WhatToCheck, InferModes, TrustFinalInsts,
+        Markers, PredId, ProcId, Body0, Body, HeadVars, InstMap0,
         ArgFinalInsts0, ArgFinalInsts, ModeInfo0, ModeInfo) :-
-    do_modecheck_proc_body(ModuleInfo, WhatToCheck, InferModes, Markers,
-        PredId, ProcId, Body0, Body1, HeadVars, InstMap0,
-        ArgFinalInsts0, ArgFinalInsts1, ModeInfo0, ModeInfo1),
+    do_modecheck_proc_body(ModuleInfo, WhatToCheck, InferModes,
+        TrustFinalInsts, Markers, PredId, ProcId, Body0, Body1, HeadVars,
+        InstMap0, ArgFinalInsts0, ArgFinalInsts1, ModeInfo0, ModeInfo1),
     mode_info_get_errors(ModeInfo1, ModeErrors1),
     (
         ModeErrors1 = [],
@@ -736,8 +743,9 @@ modecheck_proc_body(ModuleInfo, WhatToCheck, InferModes, Markers,
             mode_info_set_make_ground_terms_unique(make_ground_terms_unique,
                 ModeInfo0, ModeInfo2),
             do_modecheck_proc_body(ModuleInfo, WhatToCheck, InferModes,
-                Markers, PredId, ProcId, Body0, Body, HeadVars, InstMap0,
-                ArgFinalInsts0, ArgFinalInsts, ModeInfo2, ModeInfo)
+                TrustFinalInsts, Markers, PredId, ProcId, Body0, Body,
+                HeadVars, InstMap0, ArgFinalInsts0, ArgFinalInsts,
+                ModeInfo2, ModeInfo)
         ;
             HadFromGroundTerm = did_not_have_from_ground_term_scope,
             % The error could not have been due a ground term, so the results
@@ -749,13 +757,13 @@ modecheck_proc_body(ModuleInfo, WhatToCheck, InferModes, Markers,
     ).
 
 :- pred do_modecheck_proc_body(module_info::in, how_to_check_goal::in,
-    bool::in, pred_markers::in, pred_id::in, proc_id::in,
-    hlds_goal::in, hlds_goal::out, list(prog_var)::in, instmap::in,
-    list(mer_inst)::in, list(mer_inst)::out, mode_info::in, mode_info::out)
-    is det.
+    bool::in, trust_final_insts::in, pred_markers::in,
+    pred_id::in, proc_id::in, hlds_goal::in, hlds_goal::out,
+    list(prog_var)::in, instmap::in, list(mer_inst)::in, list(mer_inst)::out,
+    mode_info::in, mode_info::out) is det.
 
-do_modecheck_proc_body(ModuleInfo, WhatToCheck, InferModes, Markers,
-        PredId, ProcId, Body0, Body, HeadVars, InstMap0,
+do_modecheck_proc_body(ModuleInfo, WhatToCheck, InferModes, TrustFinalInsts,
+        Markers, PredId, ProcId, Body0, Body, HeadVars, InstMap0,
         ArgFinalInsts0, ArgFinalInsts, !ModeInfo) :-
     string.format("procedure_%d_%d",
         [i(pred_id_to_int(PredId)), i(proc_id_to_int(ProcId))],
@@ -865,7 +873,7 @@ do_modecheck_proc_body(ModuleInfo, WhatToCheck, InferModes, Markers,
         mode_checkpoint(exit, CheckpointMsg, !ModeInfo),
 
         % Check that final insts match those specified in the mode declaration.
-        modecheck_final_insts(HeadVars, InferModes,
+        modecheck_final_insts(HeadVars, InferModes, TrustFinalInsts,
             ArgFinalInsts0, ArgFinalInsts, Body1, Body, !ModeInfo)
     ).
 
@@ -1041,8 +1049,9 @@ modecheck_clause_disj(CheckpointMsg, HeadVars, InstMap0, ArgFinalInsts0,
     mode_checkpoint(exit, CheckpointMsg, !ModeInfo),
 
     % Check that final insts match those specified in the mode declaration.
-    modecheck_final_insts(HeadVars, no, ArgFinalInsts0,
-        _ArgFinalInsts, Disjunct1, Disjunct, !ModeInfo).
+    InferModes = no,
+    modecheck_final_insts(HeadVars, InferModes, do_not_trust_final_insts,
+        ArgFinalInsts0, _ArgFinalInsts, Disjunct1, Disjunct, !ModeInfo).
 
 :- pred modecheck_clause_switch(string::in, list(prog_var)::in, instmap::in,
     list(mer_inst)::in, prog_var::in, case::in, case::out,
@@ -1074,8 +1083,9 @@ modecheck_clause_switch(CheckpointMsg, HeadVars, InstMap0, ArgFinalInsts0,
     mode_checkpoint(exit, CheckpointMsg, !ModeInfo),
 
     % Check that final insts match those specified in the mode declaration.
-    modecheck_final_insts(HeadVars, no, ArgFinalInsts0,
-        _ArgFinalInsts, Goal2, Goal, !ModeInfo),
+    InferModes = no,
+    modecheck_final_insts(HeadVars, InferModes, do_not_trust_final_insts,
+        ArgFinalInsts0, _ArgFinalInsts, Goal2, Goal, !ModeInfo),
     Case = case(MainConsId, OtherConsIds, Goal).
 
 :- pred unique_modecheck_clause_disj(string::in, list(prog_var)::in,
@@ -1095,8 +1105,9 @@ unique_modecheck_clause_disj(CheckpointMsg, HeadVars, InstMap0, ArgFinalInsts0,
     mode_checkpoint(exit, CheckpointMsg, !ModeInfo),
 
     % Check that final insts match those specified in the mode declaration.
-    modecheck_final_insts(HeadVars, no, ArgFinalInsts0,
-        _ArgFinalInsts, Disjunct1, Disjunct, !ModeInfo).
+    InferModes = no,
+    modecheck_final_insts(HeadVars, InferModes, do_not_trust_final_insts,
+        ArgFinalInsts0, _ArgFinalInsts, Disjunct1, Disjunct, !ModeInfo).
 
 :- pred unique_modecheck_clause_switch(string::in, list(prog_var)::in,
     instmap::in, list(mer_inst)::in, prog_var::in, case::in, case::out,
@@ -1126,8 +1137,9 @@ unique_modecheck_clause_switch(CheckpointMsg, HeadVars, InstMap0,
     mode_checkpoint(exit, CheckpointMsg, !ModeInfo),
 
     % Check that final insts match those specified in the mode declaration.
-    modecheck_final_insts(HeadVars, no, ArgFinalInsts0, _ArgFinalInsts,
-        Goal2, Goal, !ModeInfo),
+    InferModes = no,
+    modecheck_final_insts(HeadVars, InferModes, do_not_trust_final_insts,
+        ArgFinalInsts0, _ArgFinalInsts, Goal2, Goal, !ModeInfo),
     Case = case(MainConsId, OtherConsIds, Goal).
 
 %-----------------------------------------------------------------------------%
@@ -1138,17 +1150,17 @@ modecheck_lambda_final_insts(HeadVars, ArgFinalInsts, !Goal, !ModeInfo) :-
     % For lambda expressions, modes must always be declared;
     % we never infer them.
     InferModes = no,
-    modecheck_final_insts(HeadVars, InferModes, ArgFinalInsts,
-        _NewFinalInsts, !Goal, !ModeInfo).
+    modecheck_final_insts(HeadVars, InferModes, do_not_trust_final_insts,
+        ArgFinalInsts, _NewFinalInsts, !Goal, !ModeInfo).
 
     % Check that the final insts of the head vars match their expected insts.
     %
 :- pred modecheck_final_insts(list(prog_var)::in, bool::in,
-    list(mer_inst)::in, list(mer_inst)::out, hlds_goal::in, hlds_goal::out,
-    mode_info::in, mode_info::out) is det.
+    trust_final_insts::in, list(mer_inst)::in, list(mer_inst)::out,
+    hlds_goal::in, hlds_goal::out, mode_info::in, mode_info::out) is det.
 
-modecheck_final_insts(HeadVars, InferModes, FinalInsts0, FinalInsts,
-        Body0, Body, !ModeInfo) :-
+modecheck_final_insts(HeadVars, InferModes, TrustFinalInsts,
+        FinalInsts0, FinalInsts, Body0, Body, !ModeInfo) :-
     mode_info_get_module_info(!.ModeInfo, ModuleInfo),
     mode_info_get_errors(!.ModeInfo, Errors),
     % If there were any mode errors, use an unreachable instmap.
@@ -1184,15 +1196,17 @@ modecheck_final_insts(HeadVars, InferModes, FinalInsts0, FinalInsts,
         module_info_proc_info(ModuleInfo, PredId, ProcId, ProcInfo),
         proc_info_arglives(ProcInfo, ModuleInfo, ArgLives),
         maybe_clobber_insts(VarFinalInsts2, ArgLives, FinalInsts),
-        check_final_insts(HeadVars, FinalInsts0, FinalInsts, InferModes, 1,
-            ModuleInfo, Body0, Body, no, Changed1, !ModeInfo),
+        check_final_insts(HeadVars, FinalInsts0, FinalInsts, InferModes,
+            TrustFinalInsts, 1, ModuleInfo, Body0, Body, no, Changed1,
+            !ModeInfo),
         mode_info_get_changed_flag(!.ModeInfo, Changed2),
         bool.or_list([Changed0, Changed1, Changed2], Changed),
         mode_info_set_changed_flag(Changed, !ModeInfo)
     ;
         InferModes = no,
         check_final_insts(HeadVars, FinalInsts0, VarFinalInsts1,
-            InferModes, 1, ModuleInfo, Body0, Body, no, _Changed1, !ModeInfo),
+            InferModes, TrustFinalInsts, 1, ModuleInfo, Body0, Body,
+            no, _Changed1, !ModeInfo),
         FinalInsts = FinalInsts0
     ).
 
@@ -1215,12 +1229,12 @@ maybe_clobber_insts([Inst0 | Insts0], [IsLive | IsLives], [Inst | Insts]) :-
     maybe_clobber_insts(Insts0, IsLives, Insts).
 
 :- pred check_final_insts(list(prog_var)::in,
-    list(mer_inst)::in, list(mer_inst)::in,
-    bool::in, int::in, module_info::in, hlds_goal::in, hlds_goal::out,
+    list(mer_inst)::in, list(mer_inst)::in, bool::in, trust_final_insts::in,
+    int::in, module_info::in, hlds_goal::in, hlds_goal::out,
     bool::in, bool::out, mode_info::in, mode_info::out) is det.
 
-check_final_insts(Vars, Insts, VarInsts, InferModes, ArgNum, ModuleInfo,
-        !Goal, !Changed, !ModeInfo) :-
+check_final_insts(Vars, Insts, VarInsts, InferModes, TrustFinalInsts, ArgNum,
+        ModuleInfo, !Goal, !Changed, !ModeInfo) :-
     (
         Vars = [],
         Insts = [],
@@ -1234,7 +1248,10 @@ check_final_insts(Vars, Insts, VarInsts, InferModes, ArgNum, ModuleInfo,
     ->
         mode_info_get_var_types(!.ModeInfo, VarTypes),
         lookup_var_type(VarTypes, Var, Type),
-        ( inst_matches_final_typed(VarInst, Inst, Type, ModuleInfo) ->
+        (
+            inst_matches_final_typed(VarInst, Inst, Type, ModuleInfo,
+                TrustFinalInsts)
+        ->
             true
         ;
             !:Changed = yes,
@@ -1283,7 +1300,8 @@ check_final_insts(Vars, Insts, VarInsts, InferModes, ArgNum, ModuleInfo,
             )
         ),
         check_final_insts(VarsTail, InstsTail, VarInstsTail,
-            InferModes, ArgNum + 1, ModuleInfo, !Goal, !Changed, !ModeInfo)
+            InferModes, TrustFinalInsts, ArgNum + 1, ModuleInfo,
+            !Goal, !Changed, !ModeInfo)
     ;
         unexpected($module, $pred, "length mismatch")
     ).
diff --git a/compiler/prog_rep.m b/compiler/prog_rep.m
index 4c51790..85c31b2 100644
--- a/compiler/prog_rep.m
+++ b/compiler/prog_rep.m
@@ -840,7 +840,7 @@ goal_info_to_atomic_goal_rep_fields(GoalInfo, Instmap0, Info, FileName, LineNo,
     term.context_line(Context, LineNo),
     InstmapDelta = goal_info_get_instmap_delta(GoalInfo),
     instmap.apply_instmap_delta(Instmap0, InstmapDelta, Instmap),
-    instmap_changed_vars(Instmap0, Instmap, Info ^ pri_vartypes,
+    instmap_changed_vars_old(Instmap0, Instmap, Info ^ pri_vartypes,
         Info ^ pri_module_info, ChangedVars),
     set_of_var.to_sorted_list(ChangedVars, BoundVars).
 
-- 
1.8.4




More information about the reviews mailing list