[m-rev.] for review: report an error for typeclasses with no parameters
Julien Fischer
jfischer at opturion.com
Wed Nov 4 17:00:37 AEDT 2015
The error message we produce for the bug #191 test case is not very good,
it refers to the wrapper procedure introduced for class methods -- I'm
working on a change to fix this. Also, ideally the compiler should not
produce the spurious warning for the new typeclass_no_params test case.
--------------
For review by anyone.
Report an error for a type class with no parameters.
The compiler was not rejecting typeclass declarations without any class
parameters, for example:
:- typeclass foo where [].
Mercury requires typeclass declarations to have at least one class
parameter.
compiler/prog_io_typeclass.m:
Emit an error if we encounter a typeclass declaration with no parameters.
tests/invalid/Mmakefile:
tests/invalid/typeclass_no_param.{m,err_exp:
Add a regression test for the above.
tests/invalid/bug191.{m,err_exp}:
Avoid having a typeclass with no parameters.
Julien.
diff --git a/compiler/prog_io_typeclass.m b/compiler/prog_io_typeclass.m
index 804537f..3f055fe 100644
--- a/compiler/prog_io_typeclass.m
+++ b/compiler/prog_io_typeclass.m
@@ -307,25 +307,37 @@ parse_unconstrained_class(ModuleName, NameTerm, TVarSet, Context, SeqNum,
(
MaybeClassName = ok2(ClassName, TermVars0),
list.map(term.coerce, TermVars0, TermVars),
- ( if
- term.term_list_to_var_list(TermVars, Vars),
- list.sort_and_remove_dups(TermVars, SortedTermVars),
- list.length(SortedTermVars, NumSortedTermVars),
- list.length(TermVars, NumTermVars),
- NumSortedTermVars = NumTermVars
- then
- % XXX Would this be a better context?
- % Context = get_term_context(NameTerm),
- TypeClassInfo = item_typeclass_info(ClassName, Vars, [], [],
- class_interface_abstract, TVarSet, Context, SeqNum),
- MaybeTypeClassInfo = ok1(TypeClassInfo)
- else
- Pieces = [words("Error: expected distinct variables"),
- words("as class parameters."), nl],
- % XXX Would Context be better than get_term_context(NameTerm)?
+ (
+ TermVars = [],
+ Pieces = [
+ words("Error: typeclass declarations require"),
+ words("at least one class parameter.")
+ ],
Spec = error_spec(severity_error, phase_term_to_parse_tree,
[simple_msg(get_term_context(NameTerm), [always(Pieces)])]),
MaybeTypeClassInfo = error1([Spec])
+ ;
+ TermVars = [_ | _],
+ ( if
+ term.term_list_to_var_list(TermVars, Vars),
+ list.sort_and_remove_dups(TermVars, SortedTermVars),
+ list.length(SortedTermVars, NumSortedTermVars),
+ list.length(TermVars, NumTermVars),
+ NumSortedTermVars = NumTermVars
+ then
+ % XXX Would this be a better context?
+ % Context = get_term_context(NameTerm),
+ TypeClassInfo = item_typeclass_info(ClassName, Vars, [], [],
+ class_interface_abstract, TVarSet, Context, SeqNum),
+ MaybeTypeClassInfo = ok1(TypeClassInfo)
+ else
+ Pieces = [words("Error: expected distinct variables"),
+ words("as class parameters."), nl],
+ % XXX Would Context be better than get_term_context(NameTerm)?
+ Spec = error_spec(severity_error, phase_term_to_parse_tree,
+ [simple_msg(get_term_context(NameTerm), [always(Pieces)])]),
+ MaybeTypeClassInfo = error1([Spec])
+ )
)
;
MaybeClassName = error2(Specs),
diff --git a/tests/invalid/Mmakefile b/tests/invalid/Mmakefile
index 06db53a..5c56d34 100644
--- a/tests/invalid/Mmakefile
+++ b/tests/invalid/Mmakefile
@@ -247,6 +247,7 @@ SINGLEMODULE= \
typeclass_mode_2 \
typeclass_mode_3 \
typeclass_mode_4 \
+ typeclass_no_param \
typeclass_test_1 \
typeclass_test_10 \
typeclass_test_11 \
diff --git a/tests/invalid/bug191.err_exp b/tests/invalid/bug191.err_exp
index 5138762..3caeb3d 100644
--- a/tests/invalid/bug191.err_exp
+++ b/tests/invalid/bug191.err_exp
@@ -1,6 +1,6 @@
bug191.m:020: In clause for
-bug191.m:020: `'ClassMethod_for_bug191__foo________bug191__baz_2'(in,
-bug191.m:020: out((bug191.a)))':
-bug191.m:020: mode error: argument 2 did not get sufficiently instantiated.
-bug191.m:020: Final instantiatedness of `HeadVar__2' was `ground',
+bug191.m:020: `'ClassMethod_for_bug191__foo____int__arity0______bug191__baz_3'(in,
+bug191.m:020: in, out((bug191.a)))':
+bug191.m:020: mode error: argument 3 did not get sufficiently instantiated.
+bug191.m:020: Final instantiatedness of `HeadVar__3' was `ground',
bug191.m:020: expected final instantiatedness was `bound(bug191.a(ground))'.
diff --git a/tests/invalid/bug191.m b/tests/invalid/bug191.m
index 3076dc5..0c06936 100644
--- a/tests/invalid/bug191.m
+++ b/tests/invalid/bug191.m
@@ -16,17 +16,17 @@
:- inst a ---> a(ground).
-:- typeclass foo where [pred baz(int::in, foo::out(a)) is det].
-:- instance foo where [pred(baz/2) is bar].
+:- typeclass foo(T) where [pred baz(T::in, int::in, foo::out(a)) is det].
+:- instance foo(int) where [pred(baz/3) is bar].
:- pred foo(foo::in(a), int::out) is det.
foo(a(I), I).
% should be bar(int::in, foo::out(a))
-:- pred bar(int::in, foo::out) is det.
-bar(_S, b("GOTCHA")).
+:- pred bar(int::in, int::in, foo::out) is det.
+bar(_, _S, b("GOTCHA")).
main(!IO) :-
- baz(42, F),
+ baz(561, 42, F),
foo(F, I),
print(I, !IO), nl(!IO).
diff --git a/tests/invalid/typeclass_no_param.err_exp b/tests/invalid/typeclass_no_param.err_exp
new file mode 100644
index 0000000..6605c23
--- /dev/null
+++ b/tests/invalid/typeclass_no_param.err_exp
@@ -0,0 +1,5 @@
+typeclass_no_param.m:004: Warning: interface for module `typeclass_no_param'
+typeclass_no_param.m:004: does not export anything.
+typeclass_no_param.m:007: Error: typeclass declarations require at least one
+typeclass_no_param.m:007: class parameter.
+For more information, recompile with `-E'.
diff --git a/tests/invalid/typeclass_no_param.m b/tests/invalid/typeclass_no_param.m
new file mode 100644
index 0000000..d11b141
--- /dev/null
+++ b/tests/invalid/typeclass_no_param.m
@@ -0,0 +1,7 @@
+% rotd-2015-11-04 and before(!) did not report an error for typeclasses with no
+% parameters.
+
+:- module typeclass_no_param.
+:- interface.
+
+:- typeclass foo where [].
More information about the reviews
mailing list