[m-rev.] for review: improved error messages for unexpected ::mode suffixes

Mark Brown mark at mercurylang.org
Sun May 22 20:30:28 AEST 2016


Hi,

This is for review by anyone.

Mark.
-------------- next part --------------
commit 23e51121e7bdf0bba6dd4c684fe235668aea7f8c
Author: Mark Brown <mark at mercurylang.org>
Date:   Sun May 22 20:18:27 2016 +1000

    Improve error messages for unexpected ::mode suffixes.
    
    compiler/parse_type_name.m:
    	In the arguments of pred and func types where we haven't
    	seen a determinism suffix, assume that uses of '::'/2
    	are mode suffixes and report them as being unexpected.
    	Previously we would typically end up reporting that '::'/2,
    	'in'/0 and 'out'/0 are undefined types.
    
    tests/invalid/combined_ho_type_inst.err_exp:
    tests/invalid/combined_ho_type_inst_2.err_exp:
    	Update expected outputs.

diff --git a/compiler/parse_type_name.m b/compiler/parse_type_name.m
index 02b1c48..8ab170f 100644
--- a/compiler/parse_type_name.m
+++ b/compiler/parse_type_name.m
@@ -216,36 +216,35 @@ parse_compound_type(AllowHOInstInfo, Term, VarSet, ContextPieces,
         Result = error1([Spec])
     ;
         CompoundTypeKind = kctk_pure_pred(Args),
-        % XXX We should update ContextPieces.
-        parse_types(no_allow_ho_inst_info(wnhii_pred_arg),
-            VarSet, ContextPieces, Args, MaybeArgTypes),
+        parse_types_no_modes(no_allow_ho_inst_info(wnhii_pred_arg),
+            VarSet, ContextPieces, Args, 1, ArgTypes, [], Specs),
         (
-            MaybeArgTypes = ok1(ArgTypes),
+            Specs = [],
             construct_higher_order_pred_type(purity_pure, lambda_normal,
                 ArgTypes, PredType),
             Result = ok1(PredType)
         ;
-            MaybeArgTypes = error1(Specs),
+            Specs = [_ | _],
             Result = error1(Specs)
         )
     ;
         CompoundTypeKind = kctk_pure_func(BeforeEqTerm, AfterEqTerm),
         ( if BeforeEqTerm = term.functor(term.atom("func"), FuncArgs, _) then
-            % XXX We should update ContextPieces.
-            parse_types(no_allow_ho_inst_info(wnhii_func_arg),
-                VarSet, ContextPieces, FuncArgs, MaybeArgTypes),
-            parse_type(no_allow_ho_inst_info(wnhii_func_return_arg),
-                VarSet, ContextPieces, AfterEqTerm, MaybeRetType),
+            parse_types_no_modes(no_allow_ho_inst_info(wnhii_func_arg),
+                VarSet, ContextPieces, FuncArgs, 1, ArgTypes, [], ArgSpecs),
+            RetContextPieces = ContextPieces ++
+                cord.from_list([words("in the return value:"), nl]),
+            parse_type_no_mode(no_allow_ho_inst_info(wnhii_func_return_arg),
+                VarSet, RetContextPieces, AfterEqTerm, MaybeRetType),
             ( if
-                MaybeArgTypes = ok1(ArgTypes),
+                ArgSpecs = [],
                 MaybeRetType = ok1(RetType)
             then
                 construct_higher_order_func_type(purity_pure, lambda_normal,
                     ArgTypes, RetType, FuncType),
                 Result = ok1(FuncType)
             else
-                Specs = get_any_errors1(MaybeArgTypes)
-                    ++ get_any_errors1(MaybeRetType),
+                Specs = ArgSpecs ++ get_any_errors1(MaybeRetType),
                 Result = error1(Specs)
             )
         else
@@ -285,37 +284,36 @@ parse_compound_type(AllowHOInstInfo, Term, VarSet, ContextPieces,
             Args = [BeforeEqTerm, AfterEqTerm],
             BeforeEqTerm = term.functor(term.atom("func"), FuncArgs, _)
         then
-            % XXX We should update ContextPieces.
-            parse_types(no_allow_ho_inst_info(wnhii_func_arg),
-                VarSet, ContextPieces, FuncArgs, MaybeArgTypes),
-            parse_type(no_allow_ho_inst_info(wnhii_func_return_arg),
-                VarSet, ContextPieces, AfterEqTerm, MaybeRetType),
+            parse_types_no_modes(no_allow_ho_inst_info(wnhii_func_arg),
+                VarSet, ContextPieces, FuncArgs, 1, ArgTypes, [], ArgSpecs),
+            RetContextPieces = ContextPieces ++
+                cord.from_list([words("in the return value:"), nl]),
+            parse_type_no_mode(no_allow_ho_inst_info(wnhii_func_return_arg),
+                VarSet, RetContextPieces, AfterEqTerm, MaybeRetType),
             ( if
-                MaybeArgTypes = ok1(ArgTypes),
+                ArgSpecs = [],
                 MaybeRetType = ok1(RetType)
             then
                 construct_higher_order_func_type(Purity, lambda_normal,
                     ArgTypes, RetType, Type),
                 Result = ok1(Type)
             else
-                Specs = get_any_errors1(MaybeArgTypes)
-                    ++ get_any_errors1(MaybeRetType),
+                Specs = ArgSpecs ++ get_any_errors1(MaybeRetType),
                 Result = error1(Specs)
             )
         else if
             SubTerm = term.functor(term.atom(Name), Args, _),
             Name = "pred"
         then
-            % XXX We should update ContextPieces.
-            parse_types(no_allow_ho_inst_info(wnhii_pred_arg),
-                VarSet, ContextPieces, Args, MaybeArgTypes),
+            parse_types_no_modes(no_allow_ho_inst_info(wnhii_pred_arg),
+                VarSet, ContextPieces, Args, 1, ArgTypes, [], Specs),
             (
-                MaybeArgTypes = ok1(ArgTypes),
+                Specs = [],
                 construct_higher_order_pred_type(Purity, lambda_normal,
                     ArgTypes, Type),
                 Result = ok1(Type)
             ;
-                MaybeArgTypes = error1(Specs),
+                Specs = [_ | _],
                 Result = error1(Specs)
             )
         else if
@@ -466,6 +464,47 @@ project_tm_type_and_mode(type_only(_), _, _) :-
 
 %---------------------------------------------------------------------------%
 
+:- pred parse_types_no_modes(allow_ho_inst_info::in, varset::in,
+    cord(format_component)::in, list(term)::in, int::in, list(mer_type)::out,
+    list(error_spec)::in, list(error_spec)::out) is det.
+
+parse_types_no_modes(_, _, _, [], _, [], !Specs).
+parse_types_no_modes(AllowHOInstInfo, Varset, ContextPieces, [Term | Terms],
+        ArgNum, Types, !Specs) :-
+    parse_types_no_modes(AllowHOInstInfo, Varset, ContextPieces, Terms,
+        ArgNum + 1, TypesTail, !Specs),
+    ArgContextPieces = ContextPieces ++
+        cord.from_list([words("in the"), nth_fixed(ArgNum),
+        words("argument:"), nl]),
+    parse_type_no_mode(AllowHOInstInfo, Varset, ArgContextPieces, Term,
+        MaybeType),
+    (
+        MaybeType = ok1(Type),
+        Types = [Type | TypesTail]
+    ;
+        MaybeType = error1(TSpecs),
+        Types = TypesTail,
+        !:Specs = TSpecs ++ !.Specs
+    ).
+
+:- pred parse_type_no_mode(allow_ho_inst_info::in, varset::in,
+    cord(format_component)::in, term::in, maybe1(mer_type)::out) is det.
+
+parse_type_no_mode(AllowHOInstInfo, Varset, ContextPieces, Term, MaybeType) :-
+    ( if Term = term.functor(term.atom("::"), [_, _], _) then
+        ErrorPieces = [lower_case_next_if_not_first,
+            words("Error: unexpected"), quote("::mode"),
+                words("suffix."), nl],
+        Pieces = cord.list(ContextPieces ++ cord.from_list(ErrorPieces)),
+        Spec = error_spec(severity_error, phase_term_to_parse_tree,
+            [simple_msg(get_term_context(Term), [always(Pieces)])]),
+        MaybeType = error1([Spec])
+    else
+        parse_type(AllowHOInstInfo, Varset, ContextPieces, Term, MaybeType)
+    ).
+
+%---------------------------------------------------------------------------%
+
 parse_type_and_modes(_, _, _, _, _, [], _, [], !Specs).
 parse_type_and_modes(MaybeInstConstraints, MaybeRequireMode, Why, VarSet,
         ContextPieces, [Term | Terms], ArgNum, TypesAndModes, !Specs) :-
diff --git a/tests/invalid/combined_ho_type_inst.err_exp b/tests/invalid/combined_ho_type_inst.err_exp
index dcff7f8..07328dd 100644
--- a/tests/invalid/combined_ho_type_inst.err_exp
+++ b/tests/invalid/combined_ho_type_inst.err_exp
@@ -16,7 +16,8 @@ combined_ho_type_inst.m:021: In type definition: error: the type
 combined_ho_type_inst.m:021:   `(((func (int :: in)) = (int :: out)) is semidet)'
 combined_ho_type_inst.m:021:   contains higher order inst information, but this
 combined_ho_type_inst.m:021:   is not allowed in a type constructor's argument.
-combined_ho_type_inst.m:024: In type definition: error: the type
+combined_ho_type_inst.m:024: In type definition: in the first argument:
+combined_ho_type_inst.m:024:   error: the type
 combined_ho_type_inst.m:024:   `(pred((int :: in), (int :: out)) is det)'
 combined_ho_type_inst.m:024:   contains higher order inst information, but this
 combined_ho_type_inst.m:024:   is not allowed in a predicate's argument.
@@ -25,7 +26,8 @@ combined_ho_type_inst.m:026:   error: the type
 combined_ho_type_inst.m:026:   `(pred((int :: in), (int :: out)) is det)'
 combined_ho_type_inst.m:026:   contains higher order inst information, but this
 combined_ho_type_inst.m:026:   is not allowed in a predicate's argument.
-combined_ho_type_inst.m:028: In type definition: error: the type
+combined_ho_type_inst.m:028: In type definition: in the first argument:
+combined_ho_type_inst.m:028:   error: the type
 combined_ho_type_inst.m:028:   `(((func (int :: in)) = (int :: out)) is semidet)'
 combined_ho_type_inst.m:028:   contains higher order inst information, but this
 combined_ho_type_inst.m:028:   is not allowed in a function's argument.
diff --git a/tests/invalid/combined_ho_type_inst_2.err_exp b/tests/invalid/combined_ho_type_inst_2.err_exp
index 2fcb440..20c620d 100644
--- a/tests/invalid/combined_ho_type_inst_2.err_exp
+++ b/tests/invalid/combined_ho_type_inst_2.err_exp
@@ -8,23 +8,9 @@ combined_ho_type_inst_2.m:024: In type definition: in the first argument:
 combined_ho_type_inst_2.m:024:   error: missing `::mode' suffix.
 combined_ho_type_inst_2.m:024: In type definition: in the return value:
 combined_ho_type_inst_2.m:024:   error: missing `::mode' suffix.
-combined_ho_type_inst_2.m:027: In the first argument of function symbol
-combined_ho_type_inst_2.m:027:   `missing_detism_p' of the type
-combined_ho_type_inst_2.m:027:   `combined_ho_type_inst_2.missing_detism_p'/0:
-combined_ho_type_inst_2.m:027:   error: undefined type `::'/2.
-combined_ho_type_inst_2.m:027: In the first argument of function symbol
-combined_ho_type_inst_2.m:027:   `missing_detism_p' of the type
-combined_ho_type_inst_2.m:027:   `combined_ho_type_inst_2.missing_detism_p'/0:
-combined_ho_type_inst_2.m:027:   error: undefined type `in'/0.
-combined_ho_type_inst_2.m:030: In the first argument of function symbol
-combined_ho_type_inst_2.m:030:   `missing_detism_f' of the type
-combined_ho_type_inst_2.m:030:   `combined_ho_type_inst_2.missing_detism_f'/0:
-combined_ho_type_inst_2.m:030:   error: undefined type `::'/2.
-combined_ho_type_inst_2.m:030: In the first argument of function symbol
-combined_ho_type_inst_2.m:030:   `missing_detism_f' of the type
-combined_ho_type_inst_2.m:030:   `combined_ho_type_inst_2.missing_detism_f'/0:
-combined_ho_type_inst_2.m:030:   error: undefined type `in'/0.
-combined_ho_type_inst_2.m:030: In the first argument of function symbol
-combined_ho_type_inst_2.m:030:   `missing_detism_f' of the type
-combined_ho_type_inst_2.m:030:   `combined_ho_type_inst_2.missing_detism_f'/0:
-combined_ho_type_inst_2.m:030:   error: undefined type `out'/0.
+combined_ho_type_inst_2.m:027: In type definition: in the first argument:
+combined_ho_type_inst_2.m:027:   error: unexpected `::mode' suffix.
+combined_ho_type_inst_2.m:030: In type definition: in the first argument:
+combined_ho_type_inst_2.m:030:   error: unexpected `::mode' suffix.
+combined_ho_type_inst_2.m:030: In type definition: in the return value:
+combined_ho_type_inst_2.m:030:   error: unexpected `::mode' suffix.


More information about the reviews mailing list