[m-rev.] for post-commit review: better error messages for arg type errors

Paul Bone paul at bone.id.au
Wed Dec 31 13:02:35 AEDT 2014


On Sat, Dec 27, 2014 at 01:18:00PM +1100, Zoltan Somogyi wrote:
> I was working on module_sub_infos (which has about 30 fields)
> when I got a huge error message. I figured it would almost be simpler
> to make this change than to try to manually dig through it.
> 

This is a useful change.  Thanks.

> Improve messages for errors in functor argument types.
> 
> compiler/typecheck_errors.m:
>     Given a type error in X = f(Y1, ..., Yn), where the type of one or more
>     of the Yi does not match the type of the corresponding argument of f,
>     we have for a long time tried to print error messages that mention
>     the expected/actual type mismatches only for those arguments.
>     However, we used to insist on both the expected and actual types
>     being uniquely known. This diff lifts that restriction, so we can
>     now generate these more focused messages if e.g. the Yi is "no",
>     whose type may be either bool or maybe(T).
> 
>     We now also try to suppress any mention of mismatches in which the actual
>     type subsumes the expected type. This usually happens when the actual
>     argument value is something like [], whose type is list(T), but the
>     expected type is a list with a known element type. If there are any
>     argument type mismatches for which this is not true, we print error
>     messages only about them.
> 
>     Don't insist on printing the entire right hand side term on a single
>     like as a fixed quoted string. For the kinds of unifications for which
>     this improvement is most useful, that term won't fit on one line.
> 
>     Be more consistent aboiut putting quotes around types in error messages.

about

(I know you can't change this now.)

>     Move a predicate next to where it is used.
> 
> compiler/prog_type.m:
>     Provide a missing utility function for the new code in typecheck_errors.m.
>
> tests/invalid/overloading.err_exp:
>     Expect the error messages we now generate for this test case.
>     This is only 10 lines, compared to the old 44 lines. The first 6
>     of those 10 set the context, and the last 4 identify the problem
>     exactly. (The motivation for this change was an error like this.)
> 
> tests/invalid/type_error_ambiguous.err_exp:
>     Expect quotes around types.


> diff --git a/compiler/typecheck_errors.m b/compiler/typecheck_errors.m
> index 5a4fd0a..fa1b4f4 100644
> --- a/compiler/typecheck_errors.m
> +++ b/compiler/typecheck_errors.m
> @@ -723,35 +723,47 @@ report_error_functor_arg_types(Info, Var, ConsDefnList, Functor, Args,
>      StrippedFunctorStr = functor_cons_id_to_string(StrippedFunctor, Args,
>          VarSet, ModuleInfo, no),
>  
> -    Pieces1 = [words("in unification of")] ++
> +    VarAndTermPieces = [words("in unification of")] ++
>          argument_name_to_pieces(VarSet, Var) ++ [nl, words("and term"),
> -        quote(StrippedFunctorStr), suffix(":"), nl,
> +        words_quote(StrippedFunctorStr), suffix(":"), nl,
>          words("type error in argument(s) of")] ++
>          functor_name_to_pieces(StrippedFunctor, Arity) ++ [suffix("."), nl],
>  
>      ConsArgTypesSet = list.map(get_callee_arg_types, ArgsTypeAssignSet),
>  
> -    % If we know the type of the function symbol, and each argument
> -    % also has at most one possible type, then we prefer to print an
> -    % error message that mentions the actual and expected types of the
> -    % arguments only for the arguments in which the two types differ.
> +    % If we have consistent information about the argument types,
> +    % we prefer to print an error message that mentions only the arguments
> +    % that may be in error.
>      (
>          list.all_same(ConsArgTypesSet),
> -        ConsArgTypesSet = [ConsArgTypes | _],
> +        ConsArgTypesSet = [ConsArgTypes | _]
> +    ->
>          assoc_list.from_corresponding_lists(Args, ConsArgTypes, ArgExpTypes),
>          TypeAssigns = list.map(get_caller_arg_assign, ArgsTypeAssignSet),
> -        find_mismatched_args(ArgExpTypes, TypeAssigns, 1,
> -            SimpleMismatches, ComplexMismatches, AllMismatches),
> -        expect(list.is_not_empty(AllMismatches), $module, $pred,
> -            "no mismatches"),
> -        ComplexMismatches = []
> -    ->
> -        Pieces2 =
> -            mismatched_args_to_pieces(SimpleMismatches, yes, VarSet, Functor),
> +        find_mismatched_args(1, ArgExpTypes, TypeAssigns,
> +            [], RevSubsumesMismatches, [], RevNoSubsumeMismatches),
> +        % RevSubsumesMismatches will contain errors where the actual type
> +        % is e.g. list(T), while the expected type is list(some_actual_type).
> +        % Since the argument may be just list(T) because it is [],
> +        % we don't mention these arguments (which are likely to be red
> +        % herrings, i.e. not the actual cause of the problem) unless
> +        % there are no arguments whose possible the actual types do not
> +        % include one that subsumes the expected type.

"whose possible the actual"  I don't know what you mean.

> @@ -1387,6 +1480,16 @@ ambiguity_error_possibilities_to_pieces([Var | Vars], VarSet,
>          TypeAssign1, TypeAssign2),
>      Pieces = HeadPieces ++ TailPieces.
>  
> +    % Check whether two types are identical, i.e. whether they can be unified
> +    % without binding any type parameters.
> +    %
> +:- pred identical_types(mer_type::in, mer_type::in) is semidet.
> +
> +identical_types(Type1, Type2) :-
> +    map.init(TypeSubst0),
> +    type_unify(Type1, Type2, [], TypeSubst0, TypeSubst),
> +    TypeSubst = TypeSubst0.
> +
>  %-----------------------------------------------------------------------------%

Should this be in the other file with subsumes_type?

>  
> -    % Check whether two types are identical, i.e. whether they can be unified
> -    % without binding any type parameters.
> -    %
> -:- pred identical_types(mer_type::in, mer_type::in) is semidet.
> -
> -identical_types(Type1, Type2) :-
> -    map.init(TypeSubst0),
> -    type_unify(Type1, Type2, [], TypeSubst0, TypeSubst),
> -    TypeSubst = TypeSubst0.
> -

Ah, it has moved.



-- 
Paul Bone



More information about the reviews mailing list