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.)
This commit is contained in:
Julien Fischer
2016-06-22 20:16:49 +10:00
parent d038639150
commit dccebb77e3
6 changed files with 191 additions and 60 deletions

View File

@@ -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])

View File

@@ -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 \

View File

@@ -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'.

View File

@@ -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
].

View File

@@ -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.

View File

@@ -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"
].