[m-rev.] for review: improve error messages for invalid determinism categories

Julien Fischer jfischer at opturion.com
Wed Jun 22 15:56:12 AEST 2016


For review by anyone.

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

Improve error messages for invalid determinism categories.

For declarations with an invalid determinism category, for example

     :- pred report_usage_error(io::di, io::uo) is et.

the error message generated by the compiler currently contains all of the term
after the `:- pred' bit.

      Error: invalid determinism category
         `(report_usage_error((io :: di), (io :: uo)) is et)'.

Change this error message so that (1) we report the kind of item that the error
is occurring in and (2) we only report the erroneous part of the term (`et' in
the above example).  Furthermore, make the error message distinguish between
predicate, function and mode declarations that occur at the top-level and those
that occur for type class methods.  Also apply this distinction to the error
messages generated when the inst term of a `with_inst` annotation is invalid.

compiler/parse_item.m:
      Make the above change to error messages generated for invalid determinism
      categories.

      Thread a value through the code that parses declarations that indicates
      whether the declaration is nested inside a type class declaration or not.

      Use that information to generate more specific error messages.

tests/invalid/Mmakefile:
tests/invalid/bad_detism_category.{m,err_exp}:
tests/invalid/bad_with_inst.{m,err_exp}:
      Add test cases for the new error messages.  (Note that none of the
      existing invalid tests covered these ones.)

Julien.

diff --git a/compiler/parse_item.m b/compiler/parse_item.m
index bd4c628..6946ae4 100644
--- a/compiler/parse_item.m
+++ b/compiler/parse_item.m
@@ -99,7 +99,8 @@ parse_item_or_marker(ModuleName, VarSet, Term, SeqNum, MaybeIOM) :-
          then
              ( if
                  parse_decl_item_or_marker(ModuleName, VarSet,
-                    Functor, ArgTerms, Context, SeqNum, MaybeIOMPrime)
+                    Functor, ArgTerms, decl_is_not_in_class,
+                    Context, SeqNum, MaybeIOMPrime)
              then
                  MaybeIOM = MaybeIOMPrime
              else
@@ -158,12 +159,21 @@ decl_functor_is_not_valid(Term, Functor) = Spec :-

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

+    % This type specifies whether the declaration we are attempting to parse
+    % occurs inside a typeclass declaration or not.
+    % XXX possibly we should also include the identity of the typeclass
+    % involved in the case where parsing the class head succeeds.
+    %
+:- type decl_in_class
+    --->    decl_is_in_class
+    ;       decl_is_not_in_class.
+
  :- pred parse_decl_item_or_marker(module_name::in, varset::in,
-    string::in, list(term)::in, prog_context::in, int::in,
-    maybe1(item_or_marker)::out) is semidet.
+    string::in, list(term)::in, decl_in_class::in, prog_context::in,
+    int::in, maybe1(item_or_marker)::out) is semidet.

  parse_decl_item_or_marker(ModuleName, VarSet, Functor, ArgTerms,
-        Context, SeqNum, MaybeIOM) :-
+        IsInClass, Context, SeqNum, MaybeIOM) :-
      require_switch_arms_det [Functor]
      (
          Functor = "module",
@@ -203,31 +213,31 @@ parse_decl_item_or_marker(ModuleName, VarSet, Functor, ArgTerms,
      ;
          Functor = "mode",
          parse_mode_defn_or_decl_item(ModuleName, VarSet, ArgTerms,
-            Context, SeqNum, allow_mode_decl_and_defn, [], MaybeIOM)
+            IsInClass, Context, SeqNum, allow_mode_decl_and_defn, [], MaybeIOM)
      ;
          ( Functor = "pred", PredOrFunc = pf_predicate
          ; Functor = "func", PredOrFunc = pf_function
          ),
          parse_pred_or_func_decl_item(ModuleName, VarSet, Functor, ArgTerms,
-            Context, SeqNum, PredOrFunc, [], [], MaybeIOM)
+            IsInClass, Context, SeqNum, PredOrFunc, [], [], MaybeIOM)
      ;
          ( Functor = "some", QuantType = quant_type_exist
          ; Functor = "all", QuantType = quant_type_univ
          ),
          parse_quant_attr(ModuleName, VarSet, Functor, ArgTerms,
-            Context, SeqNum, QuantType, cord.init, cord.init, MaybeIOM)
+            IsInClass, Context, SeqNum, QuantType, cord.init, cord.init, MaybeIOM)
      ;
          ( Functor = "=>", QuantType = quant_type_exist
          ; Functor = "<=", QuantType = quant_type_univ
          ),
          parse_constraint_attr(ModuleName, VarSet, Functor, ArgTerms,
-            Context, SeqNum, QuantType, cord.init, cord.init, MaybeIOM)
+            IsInClass, Context, SeqNum, QuantType, cord.init, cord.init, MaybeIOM)
      ;
          ( Functor = "impure", Purity = purity_impure
          ; Functor = "semipure", Purity = purity_semipure
          ),
          parse_purity_attr(ModuleName, VarSet, Functor, ArgTerms,
-            Context, SeqNum, Purity, cord.init, cord.init, MaybeIOM)
+            IsInClass, Context, SeqNum, Purity, cord.init, cord.init, MaybeIOM)
      ;
          Functor = "promise",
          parse_promise_item(VarSet, ArgTerms, Context, SeqNum, MaybeIOM)
@@ -270,18 +280,18 @@ parse_decl_item_or_marker(ModuleName, VarSet, Functor, ArgTerms,
      ).

  :- pred parse_attr_decl_item_or_marker(module_name::in, varset::in,
-    string::in, list(term)::in, prog_context::in, int::in,
+    string::in, list(term)::in, decl_in_class::in, prog_context::in, int::in,
      cord(purity_attr)::in, cord(quant_constr_attr)::in,
      maybe1(item_or_marker)::out) is semidet.

  parse_attr_decl_item_or_marker(ModuleName, VarSet, Functor, ArgTerms,
-        Context, SeqNum, PurityAttrs0, QuantConstrAttrs0, MaybeIOM) :-
+        IsInClass, Context, SeqNum, PurityAttrs0, QuantConstrAttrs0, MaybeIOM) :-
      % By coincidence, the kinds of items that may have purity,
      % quantification and/or constraint attributes on them, i.e.
      % the set item_pred_decl and item_mode_decl, is exactly the
      % set of items that may appear in class method specifications.
      %
-    % A variant of the commented-out code below for should help implement
+    % A variant of the commented-out code below should help implement
      % quantification for these kinds of promise declarations, but enabling it
      % would break the above coincidence, requiring extra checks in
      % parse_class_method_decl.
@@ -290,7 +300,7 @@ parse_attr_decl_item_or_marker(ModuleName, VarSet, Functor, ArgTerms,
      (
          Functor = "mode",
          parse_mode_defn_or_decl_item(ModuleName, VarSet, ArgTerms,
-            Context, SeqNum, allow_mode_decl_only,
+            IsInClass, Context, SeqNum, allow_mode_decl_only,
              cord.list(QuantConstrAttrs0), MaybeIOM0),
          ( if cord.is_empty(PurityAttrs0) then
              MaybeIOM = MaybeIOM0
@@ -312,13 +322,13 @@ parse_attr_decl_item_or_marker(ModuleName, VarSet, Functor, ArgTerms,
          ; Functor = "func", PredOrFunc = pf_function
          ),
          parse_pred_or_func_decl_item(ModuleName, VarSet, Functor, ArgTerms,
-            Context, SeqNum, PredOrFunc,
+            IsInClass, Context, SeqNum, PredOrFunc,
              cord.list(PurityAttrs0), cord.list(QuantConstrAttrs0), MaybeIOM)
      ;
          ( Functor = "some", QuantType = quant_type_exist
          ; Functor = "all", QuantType = quant_type_univ
          ),
-        parse_quant_attr(ModuleName, VarSet, Functor, ArgTerms,
+        parse_quant_attr(ModuleName, VarSet, Functor, ArgTerms, IsInClass,
              Context, SeqNum, QuantType, PurityAttrs0, QuantConstrAttrs0,
              MaybeIOM)
      ;
@@ -326,14 +336,14 @@ parse_attr_decl_item_or_marker(ModuleName, VarSet, Functor, ArgTerms,
          ; Functor = "<=", QuantType = quant_type_univ
          ),
          parse_constraint_attr(ModuleName, VarSet, Functor, ArgTerms,
-            Context, SeqNum, QuantType, PurityAttrs0, QuantConstrAttrs0,
+            IsInClass, Context, SeqNum, QuantType, PurityAttrs0, QuantConstrAttrs0,
              MaybeIOM)
      ;
          ( Functor = "impure", Purity = purity_impure
          ; Functor = "semipure", Purity = purity_semipure
          ),
          parse_purity_attr(ModuleName, VarSet, Functor, ArgTerms,
-            Context, SeqNum, Purity, PurityAttrs0, QuantConstrAttrs0,
+            IsInClass, Context, SeqNum, Purity, PurityAttrs0, QuantConstrAttrs0,
              MaybeIOM)
  %   ;
  %       ( Functor = "promise_exclusive", PromiseType = promise_type_exclusive
@@ -350,8 +360,8 @@ parse_attr_decl_item_or_marker(ModuleName, VarSet, Functor, ArgTerms,

  parse_class_method_decl(ModuleName, VarSet, Term, MaybeClassMethod) :-
      TermContext = get_term_context(Term),
-    parse_attributed_decl(ModuleName, VarSet, Term, TermContext, -1,
-        cord.init, cord.init, MaybeIOM),
+    parse_attributed_decl(ModuleName, VarSet, Term, decl_is_in_class,
+        TermContext, -1, cord.init, cord.init, MaybeIOM),
      (
          MaybeIOM = error1(Specs),
          MaybeClassMethod = error1(Specs)
@@ -395,17 +405,17 @@ parse_class_method_decl(ModuleName, VarSet, Term, MaybeClassMethod) :-
      ;       qca_constraint(quantifier_type, term).

  :- pred parse_quant_attr(module_name::in, varset::in,
-    string::in, list(term)::in, prog_context::in, int::in,
+    string::in, list(term)::in, decl_in_class::in, prog_context::in, int::in,
      quantifier_type::in, cord(purity_attr)::in, cord(quant_constr_attr)::in,
      maybe1(item_or_marker)::out) is det.

-parse_quant_attr(ModuleName, VarSet, Functor, ArgTerms, Context, SeqNum,
-        QuantType, !.PurityAttrs, !.QuantConstrAttrs, MaybeIOM) :-
+parse_quant_attr(ModuleName, VarSet, Functor, ArgTerms, IsInClass, Context,
+        SeqNum, QuantType, !.PurityAttrs, !.QuantConstrAttrs, MaybeIOM) :-
      ( if ArgTerms = [VarsTerm, SubTerm] then
          QuantAttr = qca_quant_vars(QuantType, VarsTerm),
          !:QuantConstrAttrs = cord.snoc(!.QuantConstrAttrs, QuantAttr),
-        parse_attributed_decl(ModuleName, VarSet, SubTerm, Context, SeqNum,
-            !.PurityAttrs, !.QuantConstrAttrs, MaybeIOM)
+        parse_attributed_decl(ModuleName, VarSet, SubTerm, IsInClass, Context,
+            SeqNum, !.PurityAttrs, !.QuantConstrAttrs, MaybeIOM)
      else
          Pieces = [words("Error: the keyword"), quote(Functor),
              words("may appear in declarations"),
@@ -417,17 +427,17 @@ parse_quant_attr(ModuleName, VarSet, Functor, ArgTerms, Context, SeqNum,
      ).

  :- pred parse_constraint_attr(module_name::in, varset::in,
-    string::in, list(term)::in, prog_context::in, int::in,
+    string::in, list(term)::in, decl_in_class::in, prog_context::in, int::in,
      quantifier_type::in, cord(purity_attr)::in, cord(quant_constr_attr)::in,
      maybe1(item_or_marker)::out) is det.

-parse_constraint_attr(ModuleName, VarSet, Functor, ArgTerms, Context, SeqNum,
+parse_constraint_attr(ModuleName, VarSet, Functor, ArgTerms, IsInClass, Context, SeqNum,
          QuantType, !.PurityAttrs, !.QuantConstrAttrs, MaybeIOM) :-
      ( if ArgTerms = [SubTerm, ConstraintsTerm] then
          ConstrAttr = qca_constraint(QuantType, ConstraintsTerm),
          !:QuantConstrAttrs = cord.snoc(!.QuantConstrAttrs, ConstrAttr),
-        parse_attributed_decl(ModuleName, VarSet, SubTerm, Context, SeqNum,
-            !.PurityAttrs, !.QuantConstrAttrs, MaybeIOM)
+        parse_attributed_decl(ModuleName, VarSet, SubTerm, IsInClass, Context,
+            SeqNum, !.PurityAttrs, !.QuantConstrAttrs, MaybeIOM)
      else
          Pieces = [words("Error: the symbol"), quote(Functor),
              words("may appear in declarations only to introduce"),
@@ -438,17 +448,17 @@ parse_constraint_attr(ModuleName, VarSet, Functor, ArgTerms, Context, SeqNum,
      ).

  :- pred parse_purity_attr(module_name::in, varset::in,
-    string::in, list(term)::in, prog_context::in, int::in,
+    string::in, list(term)::in, decl_in_class::in, prog_context::in, int::in,
      purity::in, cord(purity_attr)::in, cord(quant_constr_attr)::in,
      maybe1(item_or_marker)::out) is det.

-parse_purity_attr(ModuleName, VarSet, Functor, ArgTerms, Context, SeqNum,
+parse_purity_attr(ModuleName, VarSet, Functor, ArgTerms, IsInClass, Context, SeqNum,
          Purity, !.PurityAttrs, !.QuantConstrAttrs, MaybeIOM) :-
      ( if ArgTerms = [SubTerm] then
          PurityAttr = purity_attr(Purity),
          !:PurityAttrs = cord.snoc(!.PurityAttrs, PurityAttr),
-        parse_attributed_decl(ModuleName, VarSet, SubTerm, Context, SeqNum,
-            !.PurityAttrs, !.QuantConstrAttrs, MaybeIOM)
+        parse_attributed_decl(ModuleName, VarSet, SubTerm, IsInClass, Context,
+            SeqNum, !.PurityAttrs, !.QuantConstrAttrs, MaybeIOM)
      else
          Pieces = [words("Error: the symbol"), quote(Functor),
              words("may appear only as an annotation"),
@@ -459,16 +469,16 @@ parse_purity_attr(ModuleName, VarSet, Functor, ArgTerms, Context, SeqNum,
      ).

  :- pred parse_attributed_decl(module_name::in, varset::in, term::in,
-    prog_context::in, int::in,
+    decl_in_class::in, prog_context::in, int::in,
      cord(purity_attr)::in, cord(quant_constr_attr)::in,
      maybe1(item_or_marker)::out) is det.

-parse_attributed_decl(ModuleName, VarSet, Term, _Context, SeqNum,
+parse_attributed_decl(ModuleName, VarSet, Term, IsInClass, _Context, SeqNum,
          !.PurityAttrs, !.QuantConstrAttrs, MaybeIOM) :-
      ( if Term = term.functor(term.atom(Functor), ArgTerms, FunctorContext) then
          ( if
              parse_attr_decl_item_or_marker(ModuleName, VarSet,
-                Functor, ArgTerms, FunctorContext, SeqNum,
+                Functor, ArgTerms, IsInClass, FunctorContext, SeqNum,
                  !.PurityAttrs, !.QuantConstrAttrs, MaybeIOMPrime)
          then
              MaybeIOM = MaybeIOMPrime
@@ -640,11 +650,12 @@ make_item_avail_use(Context, SeqNum, ModuleName, Avail) :-
      ;       allow_mode_decl_only.

  :- pred parse_mode_defn_or_decl_item(module_name::in, varset::in,
-    list(term)::in, prog_context::in, int::in, maybe_allow_mode_defn::in,
+    list(term)::in, decl_in_class::in,
+    prog_context::in, int::in, maybe_allow_mode_defn::in,
      list(quant_constr_attr)::in, maybe1(item_or_marker)::out) is det.

-parse_mode_defn_or_decl_item(ModuleName, VarSet, ArgTerms, Context, SeqNum,
-        AllowModeDefn, QuantConstrAttrs, MaybeIOM) :-
+parse_mode_defn_or_decl_item(ModuleName, VarSet, ArgTerms, IsInClass, Context,
+        SeqNum, AllowModeDefn, QuantConstrAttrs, MaybeIOM) :-
      ( if ArgTerms = [SubTerm] then
          ( if
              SubTerm = term.functor(term.atom("=="), [HeadTerm, BodyTerm], _),
@@ -658,8 +669,8 @@ parse_mode_defn_or_decl_item(ModuleName, VarSet, ArgTerms, Context, SeqNum,
                  Context, SeqNum, MaybeIOM)
          else
              % This is the declaration of one mode of a predicate or function.
-            parse_mode_decl(ModuleName, VarSet, SubTerm, Context, SeqNum,
-                QuantConstrAttrs, MaybeIOM)
+            parse_mode_decl(ModuleName, VarSet, SubTerm, IsInClass, Context,
+                SeqNum, QuantConstrAttrs, MaybeIOM)
          )
      else
          Pieces = [words("Error: a"), decl("mode"), words("declaration"),
@@ -798,19 +809,28 @@ parse_clause(ModuleName, VarSet0, HeadTerm, BodyTerm0, Context, SeqNum,
      % parse_pred_or_func_decl parses a predicate or function declaration.
      %
  :- pred parse_pred_or_func_decl_item(module_name::in, varset::in,
-    string::in, list(term)::in, prog_context::in, int::in,
+    string::in, list(term)::in, decl_in_class::in, prog_context::in, int::in,
      pred_or_func::in, list(purity_attr)::in, list(quant_constr_attr)::in,
      maybe1(item_or_marker)::out) is det.

  parse_pred_or_func_decl_item(ModuleName, VarSet, Functor, ArgTerms,
-        Context, SeqNum, PredOrFunc, PurityAttrs, QuantConstrAttrs,
+        IsInClass, Context, SeqNum, PredOrFunc, PurityAttrs, QuantConstrAttrs,
          MaybeIOM) :-
      ( if ArgTerms = [Term] then
-        parse_determinism_suffix(VarSet, Term, BeforeDetismTerm,
-            MaybeMaybeDetism),
+        (
+            IsInClass = decl_is_in_class,
+            PredOrFuncDeclPieces = [words("type class"), p_or_f(PredOrFunc),
+                words("method declaration:")]
+        ;
+            IsInClass = decl_is_not_in_class,
+            PredOrFuncDeclPieces = [p_or_f(PredOrFunc), words("declaration:")]
+        ),
+        DetismContextPieces = cord.from_list([words("In")] ++ PredOrFuncDeclPieces),
+        parse_determinism_suffix(VarSet, DetismContextPieces, Term,
+            BeforeDetismTerm, MaybeMaybeDetism),
          WithInstContextPieces = cord.from_list([
-            words("In the"), quote("with_inst"), words("annotation of a"),
-            words(pred_or_func_to_string(PredOrFunc)), words("declaration:")]),
+            words("In the"), quote("with_inst"), words("annotation of a")] ++
+            PredOrFuncDeclPieces),
          parse_with_inst_suffix(VarSet, WithInstContextPieces,
              BeforeDetismTerm, BeforeWithInstTerm, MaybeWithInst),
          parse_with_type_suffix(VarSet, BeforeWithInstTerm, BeforeWithTypeTerm,
@@ -1214,14 +1234,27 @@ wrap_nth(MaybeAddPredix, ArgNum) = Component :-
  %

  :- pred parse_mode_decl(module_name::in, varset::in, term::in,
-    prog_context::in, int::in, list(quant_constr_attr)::in,
+    decl_in_class::in, prog_context::in, int::in, list(quant_constr_attr)::in,
      maybe1(item_or_marker)::out) is det.

-parse_mode_decl(ModuleName, VarSet, Term, Context, SeqNum, QuantConstrAttrs,
-        MaybeIOM) :-
-    parse_determinism_suffix(VarSet, Term, BeforeDetismTerm, MaybeMaybeDetism),
-    WithInstContextPieces = cord.from_list([words("In the"),
-        quote("with_inst"), words("annotation of a mode declaration:")]),
+parse_mode_decl(ModuleName, VarSet, Term, IsInClass, Context, SeqNum,
+        QuantConstrAttrs, MaybeIOM) :-
+    (
+        IsInClass = decl_is_in_class,
+        DeclWords = words("type class method mode")
+    ;
+        IsInClass = decl_is_not_in_class,
+        DeclWords = words("mode")
+    ),
+    DetismContextPieces = cord.from_list([
+        words("In"), DeclWords, words("declaration:")
+    ]),
+    parse_determinism_suffix(VarSet, DetismContextPieces, Term,
+        BeforeDetismTerm, MaybeMaybeDetism),
+    WithInstContextPieces = cord.from_list([
+        words("In the"), quote("with_inst"), words("annotation of a"),
+        DeclWords, words("declaration:")
+    ]),
      parse_with_inst_suffix(VarSet, WithInstContextPieces, BeforeDetismTerm,
          BeforeWithInstTerm, MaybeWithInst),
      BaseTerm = BeforeWithInstTerm,
@@ -1679,18 +1712,19 @@ parse_promise_ex_item(VarSet, Functor, ArgTerms, Context, SeqNum,

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

-    % parse_determinism_suffix(VarSet, BodyTerm, BeforeDetismTerm,
-    %   MaybeMaybeDetism):
+    % parse_determinism_suffix(VarSet, ContextPieces, BodyTerm,
+    %   BeforeDetismTerm, MaybeMaybeDetism):
      %
      % Look for a suffix of the form "is <detism>" in Term. If we find one,
      % bind MaybeMaybeDetism to ok1(yes()) wrapped around the determinism,
      % and bind BeforeDetismTerm to the other part of Term. If we don't
      % find, one, then bind MaybeMaybeDetism to ok1(no).
      %
-:- pred parse_determinism_suffix(varset::in, term::in, term::out,
-    maybe1(maybe(determinism))::out) is det.
+:- pred parse_determinism_suffix(varset::in, cord(format_component)::in,
+    term::in, term::out, maybe1(maybe(determinism))::out) is det.

-parse_determinism_suffix(VarSet, Term, BeforeDetismTerm, MaybeMaybeDetism) :-
+parse_determinism_suffix(VarSet, ContextPieces, Term, BeforeDetismTerm,
+        MaybeMaybeDetism) :-
      ( if
          Term = term.functor(term.atom("is"), Args, _),
          Args = [BeforeDetismTermPrime, DetismTerm]
@@ -1702,9 +1736,12 @@ parse_determinism_suffix(VarSet, Term, BeforeDetismTerm, MaybeMaybeDetism) :-
          then
              MaybeMaybeDetism = ok1(yes(Detism))
          else
-            TermStr = describe_error_term(VarSet, Term),
-            Pieces = [words("Error: invalid determinism category"),
-                quote(TermStr), suffix("."), nl],
+            DetismTermStr = describe_error_term(VarSet, DetismTerm),
+            Pieces = cord.list(ContextPieces) ++ [
+                lower_case_next_if_not_first,
+                words("Error: invalid determinism category"),
+                quote(DetismTermStr), suffix("."), nl
+            ],
              Spec = error_spec(severity_error, phase_term_to_parse_tree,
                  [simple_msg(get_term_context(DetismTerm), [always(Pieces)])]),
              MaybeMaybeDetism = error1([Spec])
diff --git a/tests/invalid/Mmakefile b/tests/invalid/Mmakefile
index fcbdcfb..a71e1ad 100644
--- a/tests/invalid/Mmakefile
+++ b/tests/invalid/Mmakefile
@@ -48,6 +48,7 @@ SINGLEMODULE= \
  	assert_in_interface \
  	bad_consider_used \
  	bad_detism \
+	bad_detism_category \
  	bad_end_module \
  	bad_foreign_code \
  	bad_foreign_decl \
@@ -65,6 +66,7 @@ SINGLEMODULE= \
  	bad_module_name \
  	bad_mutable \
  	bad_sv_unify_msg \
+	bad_with_inst \
  	bigtest \
  	bind_in_negated \
  	bind_var_errors \
diff --git a/tests/invalid/bad_detism_category.err_exp b/tests/invalid/bad_detism_category.err_exp
index e69de29..1b3ee74 100644
--- a/tests/invalid/bad_detism_category.err_exp
+++ b/tests/invalid/bad_detism_category.err_exp
@@ -0,0 +1,24 @@
+bad_detism_category.m:015: In predicate declaration: error: invalid determinism
+bad_detism_category.m:015:   category `et'.
+bad_detism_category.m:017: In function declaration: error: invalid determinism
+bad_detism_category.m:017:   category `et'.
+bad_detism_category.m:019: Error: no clauses for predicate
+bad_detism_category.m:019:   `report_usage_message2'/2.
+bad_detism_category.m:020: In mode declaration: error: invalid determinism
+bad_detism_category.m:020:   category `et'.
+bad_detism_category.m:022: In predicate declaration: error: invalid determinism
+bad_detism_category.m:022:   category `et'.
+bad_detism_category.m:024: In predicate declaration: error: invalid determinism
+bad_detism_category.m:024:   category `et'.
+bad_detism_category.m:025: In predicate declaration: error: invalid determinism
+bad_detism_category.m:025:   category `et'.
+bad_detism_category.m:027: In predicate declaration: error: invalid determinism
+bad_detism_category.m:027:   category `et'.
+bad_detism_category.m:030: In type class predicate method declaration: error:
+bad_detism_category.m:030:   invalid determinism category `et'.
+bad_detism_category.m:033: In type class method mode declaration: error:
+bad_detism_category.m:033:   invalid determinism category `et'.
+bad_detism_category.m:035: In type class function method declaration: error:
+bad_detism_category.m:035:   invalid determinism category `et'.
+bad_detism_category.m:037: In type class predicate method declaration: error:
+bad_detism_category.m:037:   invalid determinism category `et'.
diff --git a/tests/invalid/bad_detism_category.m b/tests/invalid/bad_detism_category.m
index e69de29..ddcec2e 100644
--- a/tests/invalid/bad_detism_category.m
+++ b/tests/invalid/bad_detism_category.m
@@ -0,0 +1,38 @@
+%----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
+%----------------------------------------------------------------------------%
+% Test the error message generated when the determinism on a pred, func, mode
+% declaration is invalid.
+%----------------------------------------------------------------------------%
+
+:- module bad_detism_category.
+:- interface.
+
+:- import_module io.
+
+    % Predmode decl.
+:- pred report_usage_error(io::di, io::uo)
+    is et.    % Context of the error should be this line.
+
+:- func test_function(T::in) = (T::out) is et.
+
+:- pred report_usage_message2(io, io).
+:- mode report_usage_message2(di, uo) is et.
+
+:- some [T] pred existsq_pred(T::out) is et.
+
+:- semipure pred smp_pred(T::out) is et.
+:- impure pred imp_pred(T::out) is et.
+
+:- pred constr_pred(T::in, T::out) is et <= foo(T).
+
+:- typeclass foo(T) where [
+    pred method1(T::in, T::out) is et,
+
+    pred method2(T, T),
+    mode method2(in, out) is et,
+
+    func method3(T::in) = (T::out) is et,
+
+    some [U] pred method4(T::in, U::out) is et
+].
diff --git a/tests/invalid/bad_with_inst.err_exp b/tests/invalid/bad_with_inst.err_exp
index e69de29..6161e2a 100644
--- a/tests/invalid/bad_with_inst.err_exp
+++ b/tests/invalid/bad_with_inst.err_exp
@@ -0,0 +1,10 @@
+bad_with_inst.m:012: In the `with_inst' annotation of a predicate declaration:
+bad_with_inst.m:012:   error: `1234' is not a valid inst.
+bad_with_inst.m:014: In the `with_inst' annotation of a function declaration:
+bad_with_inst.m:014:   error: `5678' is not a valid inst.
+bad_with_inst.m:017: In the `with_inst' annotation of a type class predicate
+bad_with_inst.m:017:   method declaration: error: `"Hello"' is not a valid
+bad_with_inst.m:017:   inst.
+bad_with_inst.m:019: In the `with_inst' annotation of a type class function
+bad_with_inst.m:019:   method declaration: error: `"World"' is not a valid
+bad_with_inst.m:019:   inst.
diff --git a/tests/invalid/bad_with_inst.m b/tests/invalid/bad_with_inst.m
index e69de29..30131e0 100644
--- a/tests/invalid/bad_with_inst.m
+++ b/tests/invalid/bad_with_inst.m
@@ -0,0 +1,20 @@
+%----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
+%----------------------------------------------------------------------------%
+% Test the error messages generated  if a `with_inst` annotation is invalid.
+%----------------------------------------------------------------------------%
+
+:- module bad_with_inst.
+:- interface.
+
+:- type t ---> t.
+
+:- pred foo_pred(T, T) `with_inst` 1234.
+
+:- func foo_func(T::in) : int `with_inst` 5678.
+
+:- typeclass bar(T) where [
+    pred method1(T, T) `with_inst` "Hello",
+
+    func method2(T) : int `with_inst` "World"
+].



More information about the reviews mailing list