[m-rev.] for review: Fix overly-conservative inst matching exposed by the previous change.
Peter Wang
novalazy at gmail.com
Tue Aug 19 18:02:29 AEST 2014
On Mon, 18 Aug 2014 16:06:37 +1000, Peter Wang <novalazy at gmail.com> wrote:
> XXX contravariance_poly is broken but that may be due to a weakness
> elsewhere
When matching a constrained inst variable A =< SubInstA on the LHS,
we matched SubInstA with the inst on the RHS. We can improve the
precision by unifying the insts.
In contravariance_poly.m, in the term `q(p)' the final inst of the first
argument of p must match_final the final inst of the first argument of
the higher-order argument of q, where
:- mode p((list(I) >> nonempty(I)), (free >> nonempty(I))) is semidet.
:- mode q(pred((nonempty(bit) >> nonempty(bit)), (free >> list(bit)))
is semidet) is semidet.
We did not substitute I = bit so this rightfully fails:
nonempty(I =< ground) match_final nonempty(bit)
compiler/inst_match.m:
Add the unification to handle_inst_var_subs_2.
compiler/prog_data.m:
Improve wording of a comment.
tests/invalid/Mmakefile:
tests/invalid/contravariance_poly2.err_exp:
tests/invalid/contravariance_poly2.m:
Add an invalid test case based on contravariance_poly.m.
---
compiler/inst_match.m | 15 ++++++++++----
compiler/prog_data.m | 4 ++--
tests/invalid/Mmakefile | 1 +
tests/invalid/contravariance_poly2.err_exp | 22 ++++++++++++++++++++
tests/invalid/contravariance_poly2.m | 32 ++++++++++++++++++++++++++++++
5 files changed, 68 insertions(+), 6 deletions(-)
create mode 100644 tests/invalid/contravariance_poly2.err_exp
create mode 100644 tests/invalid/contravariance_poly2.m
diff --git a/compiler/inst_match.m b/compiler/inst_match.m
index c475ce5..88c4371 100644
--- a/compiler/inst_match.m
+++ b/compiler/inst_match.m
@@ -516,14 +516,21 @@ handle_inst_var_subs_2(Recurse, Continue, InstA, InstB, Type, !Info) :-
% inst represented by the constrained_inst_var.
% We pass `Live = is_dead' because we want
% abstractly_unify(unique, unique) = unique, not shared.
- Live = is_dead,
ModuleInfo0 = !.Info ^ imi_module_info,
- abstractly_unify_inst(Live, InstA, SubInstB, fake_unify,
+ abstractly_unify_inst(is_dead, InstA, SubInstB, fake_unify,
Inst, _Det, ModuleInfo0, ModuleInfo),
!Info ^ imi_module_info := ModuleInfo,
update_inst_var_sub(InstVarsB, Inst, Type, !Info)
- ; InstA = constrained_inst_vars(_InstVarsA, SubInstA) ->
- Recurse(SubInstA, InstB, Type, !Info)
+ ; InstA = constrained_inst_vars(InstVarsA, _SubInstA) ->
+ % InstA is a constrained_inst_var with upper bound SubInstA.
+ % Unify the insts improve upon SubInstA.
+ ModuleInfo0 = !.Info ^ imi_module_info,
+ abstractly_unify_inst(is_dead, InstA, InstB, fake_unify,
+ Inst, _Det, ModuleInfo0, ModuleInfo),
+ !Info ^ imi_module_info := ModuleInfo,
+ update_inst_var_sub(InstVarsA, Inst, Type, !Info),
+
+ Recurse(Inst, InstB, Type, !Info)
;
Continue(InstA, InstB, Type, !Info)
).
diff --git a/compiler/prog_data.m b/compiler/prog_data.m
index a9f04f2..ad65010 100644
--- a/compiler/prog_data.m
+++ b/compiler/prog_data.m
@@ -2234,8 +2234,8 @@ get_type_kind(kinded_type(_, Kind)) = Kind.
; constrained_inst_vars(set(inst_var), mer_inst)
% Constrained_inst_vars is a set of inst variables that are
- % constrained to have the same uniqueness as and to match_final
- % the specified inst.
+ % constrained to have the same uniqueness as the specified
+ % inst, and to match_final the specified inst.
; defined_inst(inst_name)
% A defined_inst is possibly recursive inst whose value is
diff --git a/tests/invalid/Mmakefile b/tests/invalid/Mmakefile
index 6341235..7b06e04 100644
--- a/tests/invalid/Mmakefile
+++ b/tests/invalid/Mmakefile
@@ -74,6 +74,7 @@ SINGLEMODULE= \
constrained_poly_insts \
constraint_proof_bug_lib \
constructor_warning \
+ contravariance_poly2 \
cyclic_typeclass \
cyclic_typeclass_2 \
cyclic_typeclass_3 \
diff --git a/tests/invalid/contravariance_poly2.err_exp b/tests/invalid/contravariance_poly2.err_exp
new file mode 100644
index 0000000..ac01a46
--- /dev/null
+++ b/tests/invalid/contravariance_poly2.err_exp
@@ -0,0 +1,22 @@
+Error: file `contravariance_poly2.m' contains the wrong module.
+ Expected module `contravariance_poly2', found module `contravariance_poly22'.
+contravariance_poly2.m:001: Error: source file `contravariance_poly2.m'
+contravariance_poly2.m:001: contains module named `contravariance_poly22'.
+contravariance_poly2.m:011: In clause for `main(di, uo)':
+contravariance_poly2.m:011: in argument 1 of call to predicate
+contravariance_poly2.m:011: `contravariance_poly22.q'/1:
+contravariance_poly2.m:011: mode error: variable `V_8' has instantiatedness
+contravariance_poly2.m:011: `/* unique */(pred(($typed_inst(list.list(int),
+contravariance_poly2.m:011: list.list((V_1 =< ground))) >>
+contravariance_poly2.m:011: $typed_inst(list.list(int), list.list((V_1 =<
+contravariance_poly2.m:011: ground)))), (free >> $typed_inst(list.list(int),
+contravariance_poly2.m:011: contravariance_poly22.nonempty((V_1 =<
+contravariance_poly2.m:011: ground))))) is semidet)',
+contravariance_poly2.m:011: expected instantiatedness was
+contravariance_poly2.m:011: `(pred(($typed_inst(list.list(int),
+contravariance_poly2.m:011: contravariance_poly22.nonempty((contravariance_poly22.bit)))
+contravariance_poly2.m:011: >> $typed_inst(list.list(int),
+contravariance_poly2.m:011: contravariance_poly22.nonempty((contravariance_poly22.bit)))),
+contravariance_poly2.m:011: (free >> $typed_inst(list.list(int),
+contravariance_poly2.m:011: list.list((contravariance_poly22.bit))))) is
+contravariance_poly2.m:011: semidet)'.
diff --git a/tests/invalid/contravariance_poly2.m b/tests/invalid/contravariance_poly2.m
new file mode 100644
index 0000000..977ebd7
--- /dev/null
+++ b/tests/invalid/contravariance_poly2.m
@@ -0,0 +1,32 @@
+:- module contravariance_poly22.
+:- interface.
+:- import_module io.
+
+:- pred main(io__state::di, io__state::uo) is det.
+
+:- implementation.
+:- import_module list, bool.
+
+main -->
+ ( { q(r) } ->
+ print("yes"), nl
+ ;
+ print("no"), nl
+ ).
+
+:- inst nonempty(I) ---> [I | list(I)].
+
+:- type intlist == list(int).
+:- inst bit == bound(0 ; 1).
+
+:- pred r(intlist, intlist).
+:- mode r((list(I) >> list(I)), (free >> nonempty(I))) is semidet.
+
+r([X], [X]).
+r([X,Y|Zs], [Y,X|Zs]).
+
+:- pred q(pred(intlist, intlist)).
+:- mode q(pred((nonempty(bit) >> nonempty(bit)), (free >> list(bit)))
+ is semidet) is semidet.
+
+q(P) :- P([1], L), L \= [].
--
1.8.4
More information about the reviews
mailing list