diff: clean up handling of unbound type variables
Fergus Henderson
fjh at cs.mu.oz.au
Fri Jan 2 11:07:50 AEDT 1998
On 01-Jan-1998, Fergus Henderson <fjh at cs.mu.oz.au> wrote:
>
> Clean up the handling of unbound type variables.
> Fix a bug with unbound type variables in lambda expressions.
>
> compiler/typecheck.m:
> compiler/purity.m:
> Move the code for checking for unbound type variables
> from typecheck.m to purity.m. It needs to be done
> *after* type inference has been completed, so it
> can't be done in the ordinary type checking/inference
> passes. Add code to purity.m to bind the
> unbound type variables to `void'.
>
> compiler/polymorphism.m:
> Comment out old code to bind unbound type variables
> to `void'; the old code was incomplete, and this
> is now done in purity.m.
>
> compiler/notes/compiler_design.html:
> Document the above changes.
>
> tests/valid/Mmakefile:
> tests/valid/unbound_tvar_in_lambda.m:
> Regression test.
Hmm, I did a bit more testing and found a few more problems,
which I have now fixed. In particular I had to change mercury_compile.m
as described below and I needed to make a few changes to the expected
output for the test cases.
--------------------
Estimated hours taken: 8
Clean up the handling of unbound type variables.
Fix a bug with unbound type variables in lambda expressions.
Run purity analysis, modechecking etc. even if there were type errors.
compiler/mercury_compile.m:
Run purity analysis, modechecking etc. even if there were type
errors. This fixes a bug (inconsistency between the code and
the comments) that seems to have been introduced in stayl's
change to mercury_compile.m (revision 1.25) to add intermodule
unused argument elimination: the comment said "continue,
even if type checking found errors", but the code did not
continue.
This change was needed to ensure that we still report a warning
message about unused type variables for tests/invalid/error2.m;
without it, we stop after type checking and don't do purity
analysis, and so don't report the warning.
compiler/typecheck.m:
compiler/purity.m:
Move the code for checking for unbound type variables
from typecheck.m to purity.m. It needs to be done
*after* type inference has been completed, so it
can't be done in the ordinary type checking/inference
passes. Add code to purity.m to bind the
unbound type variables to the builtin type `void'.
compiler/polymorphism.m:
Comment out old code to bind unbound type variables
to `void'; the old code was incomplete, and this
is now done in purity.m.
compiler/notes/compiler_design.html:
Document the above changes.
tests/valid/Mmakefile:
tests/valid/unbound_tvar_in_lambda.m:
Regression test for the above-mentioned bug with unbound type
variables in lambda expressions.
tests/warnings/singleton_test.exp:
tests/invalid/errors2.err_exp:
Change the expected warning message for unbound type variables.
The error context is not as precise as it used to be, I'm afraid:
we only know which function/predicate the error occurred in,
not which clause. Also it now comes out in a different order
relative to the other error messages.
tests/invalid/errors2.err_exp:
tests/invalid/funcs_as_preds.err_exp:
Add some new error/warning messages that are output now that
we run mode and determinism analysis even if there are type errors.
--
cvs diff compiler/mercury_compile.m compiler/notes/compiler_design.html compiler/polymorphism.m compiler/purity.m compiler/typecheck.m tests/invalid/errors2.err_exp tests/invalid/funcs_as_preds.err_exp tests/valid/Mmakefile tests/valid/unbound_tvar_in_lambda.m tests/warnings/singleton_test.exp
Index: compiler/mercury_compile.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mercury_compile.m,v
retrieving revision 1.68
diff -u -r1.68 mercury_compile.m
--- mercury_compile.m 1997/12/22 06:58:27 1.68
+++ mercury_compile.m 1998/01/01 11:01:40
@@ -428,12 +428,22 @@
{ HLDS = HLDS3 },
{ FoundError = FoundTypeError }
;
+ % only write out the `.opt' file if there are no type errors
+ globals__io_lookup_bool_option(make_optimization_interface,
+ MakeOptInt),
( { FoundTypeError = no } ->
- mercury_compile__maybe_write_optfile(MakeOptInt,
- HLDS3, HLDS4), !,
- ( { MakeOptInt = no } ->
+ mercury_compile__maybe_write_optfile(MakeOptInt,
+ HLDS3, HLDS4), !
+ ;
+ { HLDS4 = HLDS3 }
+ ),
+ % if our job was to write out the `.opt' file, then we're done
+ ( { MakeOptInt = yes } ->
+ { HLDS = HLDS4 },
+ { FoundError = FoundTypeError }
+ ;
%
- % We can't continue after an undefined insts/mode
+ % We can't continue after an undefined inst/mode
% error, since mode analysis would get internal errors
%
( { FoundUndefModeError = yes } ->
@@ -452,25 +462,16 @@
{ bool__or(FoundTypeError, FoundModeOrDetError,
FoundError) }
)
- ;
- { HLDS = HLDS4 },
- { FoundError = FoundTypeError }
- )
- ;
- { FoundError = yes },
- { HLDS = HLDS3 }
)
)
).
-:- pred mercury_compile__maybe_write_optfile(bool::out, module_info::in,
+:- pred mercury_compile__maybe_write_optfile(bool::in, module_info::in,
module_info::out, io__state::di, io__state::uo) is det.
mercury_compile__maybe_write_optfile(MakeOptInt, HLDS0, HLDS) -->
- globals__io_lookup_bool_option(make_optimization_interface,
- MakeOptInt),
globals__io_lookup_bool_option(intermod_unused_args, IntermodArgs),
globals__io_lookup_bool_option(verbose, Verbose),
globals__io_lookup_bool_option(statistics, Stats),
Index: compiler/polymorphism.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/polymorphism.m,v
retrieving revision 1.120
diff -u -r1.120 polymorphism.m
--- polymorphism.m 1997/12/22 09:56:14 1.120
+++ polymorphism.m 1998/01/01 08:43:47
@@ -1418,6 +1418,7 @@
% Given a list of types, create a list of variables to hold the type_info
% for those types, and create a list of goals to initialize those type_info
% variables to the appropriate type_info structures for the types.
+% Update the varset and vartypes accordingly.
:- pred polymorphism__make_type_info_vars(list(type),
list(var), list(hlds_goal), poly_info, poly_info).
@@ -1501,7 +1502,7 @@
Index, ExtraGoals, Var, Info0, Info)
)
;
- Type = term__variable(TypeVar1)
+ Type = term__variable(_TypeVar1)
->
% This occurs for code where a predicate calls a polymorphic
% predicate with an unbound type variable, for example
@@ -1509,7 +1510,16 @@
% :- pred p.
% :- pred q(list(T)).
% p :- q([]).
- %
+
+ % this case is now treated as an error;
+ % it should be caught by purity.m.
+ error("polymorphism__make_var: unbound type variable")
+/************
+This is what we used to do... but this didn't handle the case of type
+variables used by lambda expressions properly.
+Binding unbound type variables to `void' is now done in purity.m,
+because it is easier to do it correctly there.
+
% In this case T is unbound, so there cannot be any objects
% of type T, and so q/1 cannot possibly use the unification
% predicate for type T. We pass the type-info for the
@@ -1539,6 +1549,7 @@
map__det_insert(TypeInfoMap1, TypeVar1, type_info(Var),
TypeInfoMap),
Info = poly_info(A, B, C, TypeInfoMap, E, F, G, H)
+***************/
;
error("polymorphism__make_var: unknown type")
).
Index: compiler/purity.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/purity.m,v
retrieving revision 1.3
diff -u -r1.3 purity.m
--- purity.m 1997/12/19 03:08:03 1.3
+++ purity.m 1998/01/01 08:35:37
@@ -6,10 +6,28 @@
%
% File : purity.m
% Authors : pets (Peter Schachte)
-% Purpose : handle `impure' and `promise_pure' declarations
+% Purpose : handle `impure' and `promise_pure' declarations;
+% finish off type checking.
%
-% The purpose of this module is to allow one to declare certain parts of
-% one's program to be impure, thereby forbidding the compiler from making
+% The main purpose of this module is check the consistency of the
+% `impure' and `promise_pure' (etc.) declarations, and to thus report
+% error messages if the program is not "purity-correct".
+%
+% This module also does two final parts of type analysis:
+% - it resolves predicate overloading
+% (perhaps it ought to also resolve function overloading,
+% converting unifications that are function calls into
+% HLDS call instructions, but currently that is still done
+% in modecheck_unify.m)
+% - it checks for unbound type variables and if there are any,
+% it reports an error (or a warning, binding them to the type `void').
+% These actions cannot be done until after type inference is complete,
+% so they need to be a separate "post-typecheck pass"; they are done
+% here in combination with the purity-analysis pass for efficiency reasons.
+%
+%
+% The aim of Mercury's purity system is to allow one to declare certain parts
+% of one's program to be impure, thereby forbidding the compiler from making
% certain optimizations to that part of the code. Since one can often
% implement a perfectly pure predicate or function in terms of impure
% predicates and functions, one is also allowed to promise to the compiler
@@ -217,27 +235,188 @@
NumErrors0, NumErrors) -->
{ module_info_preds(ModuleInfo0, Preds0) },
{ map__lookup(Preds0, PredId, PredInfo0) },
- ( { pred_info_is_imported(PredInfo0)
- ; pred_info_is_pseudo_imported(PredInfo0)} ->
+ (
+ { pred_info_is_imported(PredInfo0)
+ ; pred_info_is_pseudo_imported(PredInfo0) }
+ ->
{ ModuleInfo1 = ModuleInfo0 },
{ NumErrors1 = NumErrors0 }
;
write_pred_progress_message("% Purity-checking ", PredId,
ModuleInfo0),
- puritycheck_pred(PredId, PredInfo0, PredInfo1, ModuleInfo0,
- ErrsInThisPred),
- { map__det_update(Preds0, PredId, PredInfo1, Preds) },
+ check_type_bindings(PredId, PredInfo0, PredInfo1, ModuleInfo0,
+ UnboundTypeErrsInThisPred),
+ puritycheck_pred(PredId, PredInfo1, PredInfo2, ModuleInfo0,
+ PurityErrsInThisPred),
+ { map__det_update(Preds0, PredId, PredInfo2, Preds) },
{ module_info_get_predicate_table(ModuleInfo0, PredTable0) },
{ predicate_table_set_preds(PredTable0, Preds, PredTable) },
{ module_info_set_predicate_table(ModuleInfo0, PredTable,
ModuleInfo1) },
- { NumErrors1 is NumErrors0 + ErrsInThisPred }
+ { NumErrors1 is NumErrors0 + UnboundTypeErrsInThisPred
+ + PurityErrsInThisPred }
),
check_preds_purity_2(PredIds, ModuleInfo1, ModuleInfo,
NumErrors1, NumErrors).
% Purity-check the code for single predicate, reporting any errors.
+
+%-----------------------------------------------------------------------------%
+% Check for unbound type variables
+%
+% Check that the all of the types which have been inferred
+% for the variables in the clause do not contain any unbound type
+% variables other than those that occur in the types of head
+% variables.
+
+:- pred check_type_bindings(pred_id, pred_info, pred_info,
+ module_info, int, io__state, io__state).
+:- mode check_type_bindings(in, in, out, in, out, di, uo) is det.
+
+check_type_bindings(PredId, PredInfo0, PredInfo, ModuleInfo, NumErrors,
+ IOState0, IOState) :-
+ pred_info_clauses_info(PredInfo0, ClausesInfo0),
+ ClausesInfo0 = clauses_info(VarSet, B, VarTypesMap0, HeadVars, E),
+ map__apply_to_list(HeadVars, VarTypesMap0, HeadVarTypes),
+ term__vars_list(HeadVarTypes, HeadVarTypeParams),
+ map__to_assoc_list(VarTypesMap0, VarTypesList),
+ set__init(Set0),
+ check_type_bindings_2(VarTypesList, HeadVarTypeParams,
+ [], Errs, Set0, Set),
+ ( Errs = [] ->
+ PredInfo = PredInfo0,
+ IOState = IOState0,
+ NumErrors = 0
+ ;
+ %
+ % report the warning
+ %
+ report_unresolved_type_warning(Errs, PredId, PredInfo0,
+ ModuleInfo, VarSet, IOState0, IOState),
+ NumErrors = 0,
+
+ %
+ % bind all the type variables in `Set' to `void' ...
+ %
+ pred_info_context(PredInfo0, Context),
+ bind_type_vars_to_void(Set, Context, VarTypesMap0, VarTypesMap),
+ ClausesInfo = clauses_info(VarSet, B, VarTypesMap, HeadVars, E),
+ pred_info_set_clauses_info(PredInfo0, ClausesInfo, PredInfo)
+ ).
+
+:- pred check_type_bindings_2(assoc_list(var, (type)), list(var),
+ assoc_list(var, (type)), assoc_list(var, (type)),
+ set(tvar), set(tvar)).
+:- mode check_type_bindings_2(in, in, in, out, in, out) is det.
+
+check_type_bindings_2([], _, Errs, Errs, Set, Set).
+check_type_bindings_2([Var - Type | VarTypes], HeadTypeParams,
+ Errs0, Errs, Set0, Set) :-
+ term__vars(Type, TVars),
+ set__list_to_set(TVars, TVarsSet0),
+ set__delete_list(TVarsSet0, HeadTypeParams, TVarsSet1),
+ ( \+ set__empty(TVarsSet1) ->
+ Errs1 = [Var - Type | Errs0],
+ set__union(Set0, TVarsSet1, Set1)
+ ;
+ Errs1 = Errs0,
+ Set0 = Set1
+ ),
+ check_type_bindings_2(VarTypes, HeadTypeParams,
+ Errs1, Errs, Set1, Set).
+
+%
+% bind all the type variables in `UnboundTypeVarsSet' to the type `void' ...
+%
+:- pred bind_type_vars_to_void(set(var), term__context,
+ map(var, type), map(var, type)).
+:- mode bind_type_vars_to_void(in, in, in, out) is det.
+
+bind_type_vars_to_void(UnboundTypeVarsSet, Context,
+ VarTypesMap0, VarTypesMap) :-
+ %
+ % first create a pair of corresponding lists (UnboundTypeVars, Voids)
+ % that map the unbound type variables to void
+ %
+ set__to_sorted_list(UnboundTypeVarsSet, UnboundTypeVars),
+ list__length(UnboundTypeVars, Length),
+ Void = term__functor(term__atom("void"), [], Context),
+ list__duplicate(Length, Void, Voids),
+
+ %
+ % then apply the substitution we just created to the variable types
+ %
+ map__keys(VarTypesMap0, Vars),
+ map__values(VarTypesMap0, Types0),
+ term__substitute_corresponding_list(UnboundTypeVars, Voids,
+ Types0, Types),
+ map__from_corresponding_lists(Vars, Types, VarTypesMap).
+
+%
+% report an error: uninstantiated type parameter
+%
+:- pred report_unresolved_type_warning(assoc_list(var, (type)), pred_id,
+ pred_info, module_info, varset, io__state, io__state).
+:- mode report_unresolved_type_warning(in, in, in, in, in, di, uo) is det.
+
+report_unresolved_type_warning(Errs, PredId, PredInfo, ModuleInfo, VarSet) -->
+ globals__io_lookup_bool_option(halt_at_warn, HaltAtWarn),
+ ( { HaltAtWarn = yes } ->
+ io__set_exit_status(1)
+ ;
+ []
+ ),
+
+ { pred_info_typevarset(PredInfo, TypeVarSet) },
+ { pred_info_context(PredInfo, Context) },
+
+ prog_out__write_context(Context),
+ io__write_string("In "),
+ hlds_out__write_pred_id(ModuleInfo, PredId),
+ io__write_string(":\n"),
+
+ prog_out__write_context(Context),
+ io__write_string(" warning: unresolved polymorphism.\n"),
+ prog_out__write_context(Context),
+ ( { Errs = [_] } ->
+ io__write_string(" The variable with an unbound type was:\n")
+ ;
+ io__write_string(" The variables with unbound types were:\n")
+ ),
+ write_type_var_list(Errs, Context, VarSet, TypeVarSet),
+ prog_out__write_context(Context),
+ io__write_string(" The unbound type variable(s) will be implicitly\n"),
+ prog_out__write_context(Context),
+ io__write_string(" bound to the builtin type `void'.\n"),
+ globals__io_lookup_bool_option(verbose_errors, VerboseErrors),
+ ( { VerboseErrors = yes } ->
+ io__write_strings([
+"\tThe body of the clause contains a call to a polymorphic predicate,\n",
+"\tbut I can't determine which version should be called,\n",
+"\tbecause the type variables listed above didn't get bound.\n",
+% "\tYou may need to use an explicit type qualifier.\n",
+% XXX improve error message
+"\t(I ought to tell you which call caused the problem, but I'm afraid\n",
+"\tyou'll have to work it out yourself. My apologies.)\n"
+ ])
+ ;
+ []
+ ).
+
+:- pred write_type_var_list(assoc_list(var, (type)), term__context,
+ varset, tvarset, io__state, io__state).
+:- mode write_type_var_list(in, in, in, in, di, uo) is det.
+
+write_type_var_list([], _, _, _) --> [].
+write_type_var_list([Var - Type | Rest], Context, VarSet, TVarSet) -->
+ prog_out__write_context(Context),
+ io__write_string(" "),
+ mercury_output_var(Var, VarSet, no),
+ io__write_string(" :: "),
+ mercury_output_term(Type, TVarSet, no),
+ io__write_string("\n"),
+ write_type_var_list(Rest, Context, VarSet, TVarSet).
%-----------------------------------------------------------------------------%
% Check purity of a single predicate
Index: compiler/typecheck.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/typecheck.m,v
retrieving revision 1.223
diff -u -r1.223 typecheck.m
--- typecheck.m 1997/12/19 03:08:31 1.223
+++ typecheck.m 1998/01/01 08:35:44
@@ -625,17 +625,8 @@
typecheck_check_for_ambiguity(StuffToCheck, HeadVars,
TypeCheckInfo0, TypeCheckInfo) :-
typecheck_info_get_type_assign_set(TypeCheckInfo0, TypeAssignSet),
- ( TypeAssignSet = [TypeAssign] ->
- typecheck_info_get_found_error(TypeCheckInfo0, FoundError),
- (
- StuffToCheck = whole_pred,
- FoundError = no
- ->
- check_type_bindings(TypeAssign, HeadVars,
- TypeCheckInfo0, TypeCheckInfo)
- ;
- TypeCheckInfo = TypeCheckInfo0
- )
+ ( TypeAssignSet = [_SingleTypeAssign] ->
+ TypeCheckInfo = TypeCheckInfo0
; TypeAssignSet = [TypeAssign1, TypeAssign2 | _] ->
%
% we only report an ambiguity error if
@@ -693,139 +684,6 @@
error("internal error in typechecker: no type-assignment"),
TypeCheckInfo = TypeCheckInfo0
).
-
- % Check that the all of the types which have been inferred
- % for the variables in the clause do not contain any unbound type
- % variables other than those that occur in the types of head
- % variables.
-
-:- pred check_type_bindings(type_assign, list(var),
- typecheck_info, typecheck_info).
-:- mode check_type_bindings(in, in,
- typecheck_info_di, typecheck_info_uo) is det.
-
-check_type_bindings(TypeAssign, HeadVars, TypeCheckInfo0, TypeCheckInfo) :-
- type_assign_get_type_bindings(TypeAssign, TypeBindings),
- type_assign_get_var_types(TypeAssign, VarTypesMap),
- map__apply_to_list(HeadVars, VarTypesMap, HeadVarTypes0),
- term__apply_rec_substitution_to_list(HeadVarTypes0, TypeBindings,
- HeadVarTypes),
- term__vars_list(HeadVarTypes, HeadVarTypeParams),
- map__to_assoc_list(VarTypesMap, VarTypesList),
- set__init(Set0),
- check_type_bindings_2(VarTypesList, TypeBindings, HeadVarTypeParams,
- [], Errs, Set0, _Set),
- % ... we could at this point bind all the type variables in `Set'
- % to `void' ...
- ( Errs = [] ->
- TypeCheckInfo = TypeCheckInfo0
- ;
- type_assign_get_typevarset(TypeAssign, TVarSet),
- report_unresolved_type_error(Errs, TVarSet, TypeCheckInfo0,
- TypeCheckInfo)
- ).
-
-:- pred check_type_bindings_2(assoc_list(var, (type)), tsubst, headtypes,
- assoc_list(var, (type)), assoc_list(var, (type)),
- set(tvar), set(tvar)).
-:- mode check_type_bindings_2(in, in, in, in, out, in, out) is det.
-
-check_type_bindings_2([], _, _, Errs, Errs, Set, Set).
-check_type_bindings_2([Var - Type0 | VarTypes], TypeBindings, HeadTypeParams,
- Errs0, Errs, Set0, Set) :-
- term__apply_rec_substitution(Type0, TypeBindings, Type),
- term__vars(Type, TVars),
- set__list_to_set(TVars, TVarsSet0),
- set__delete_list(TVarsSet0, HeadTypeParams, TVarsSet1),
- ( \+ set__empty(TVarsSet1) ->
- Errs1 = [Var - Type | Errs0],
- set__union(Set0, TVarsSet1, Set1)
- ;
- Errs1 = Errs0,
- Set0 = Set1
- ),
- check_type_bindings_2(VarTypes, TypeBindings, HeadTypeParams,
- Errs1, Errs, Set1, Set).
-
- % report a warning: uninstantiated type parameter
-
-:- pred report_unresolved_type_error(assoc_list(var, (type)), tvarset,
- typecheck_info, typecheck_info).
-:- mode report_unresolved_type_error(in, in, typecheck_info_di,
- typecheck_info_uo) is det.
-
-report_unresolved_type_error(Errs, TVarSet, TypeCheckInfo0, TypeCheckInfo) :-
- typecheck_info_get_io_state(TypeCheckInfo0, IOState0),
- globals__io_lookup_bool_option(infer_types, Inferring,
- IOState0, IOState1),
- ( Inferring = yes ->
- %
- % If type inferences is enabled, it can result in spurious
- % unresolved type warnings in the early passes; the warnings
- % may be spurious because the types may get resolved in later
- % passes. Unfortunately there's no way to tell which
- % is the last pass until after it is finished...
- % probably these warnings ought to be issued in a different
- % pass than type checking.
- %
- % For the moment, if type inference is enabled, you just don't
- % get these warnings.
- %
- IOState = IOState1
- ;
- report_unresolved_type_error_2(TypeCheckInfo0, Errs, TVarSet,
- IOState1, IOState)
- ),
- typecheck_info_set_io_state(TypeCheckInfo0, IOState, TypeCheckInfo).
- % Currently it is just a warning, not an error.
- % typecheck_info_set_found_error(TypeCheckInfo1, yes, TypeCheckInfo).
-
-:- pred report_unresolved_type_error_2(typecheck_info, assoc_list(var, (type)),
- tvarset, io__state, io__state).
-:- mode report_unresolved_type_error_2(typecheck_info_no_io, in, in, di, uo)
- is det.
-
-report_unresolved_type_error_2(TypeCheckInfo, Errs, TVarSet) -->
- write_typecheck_info_context(TypeCheckInfo),
- { typecheck_info_get_varset(TypeCheckInfo, VarSet) },
- { typecheck_info_get_context(TypeCheckInfo, Context) },
- io__write_string(" warning: unresolved polymorphism.\n"),
- prog_out__write_context(Context),
- ( { Errs = [_] } ->
- io__write_string(" The variable with an unbound type was:\n")
- ;
- io__write_string(" The variables with unbound types were:\n")
- ),
- write_type_var_list(Errs, Context, VarSet, TVarSet),
- prog_out__write_context(Context),
- io__write_string(" The unbound type variable(s) will be implicitly\n"),
- prog_out__write_context(Context),
- io__write_string(" bound to the builtin type `void'.\n"),
- globals__io_lookup_bool_option(verbose_errors, VerboseErrors),
- ( { VerboseErrors = yes } ->
- io__write_string("\tThe body of the clause contains a call to a polymorphic predicate,\n"),
- io__write_string("\tbut I can't determine which version should be called,\n"),
- io__write_string("\tbecause the type variables listed above didn't get bound.\n"),
- % XXX improve error message
- io__write_string("\t(I ought to tell you which call caused the problem, but I'm afraid\n"),
- io__write_string("\tyou'll have to work it out yourself. My apologies.)\n")
- ;
- []
- ).
-
-:- pred write_type_var_list(assoc_list(var, (type)), term__context,
- varset, tvarset, io__state, io__state).
-:- mode write_type_var_list(in, in, in, in, di, uo) is det.
-
-write_type_var_list([], _, _, _) --> [].
-write_type_var_list([Var - Type | Rest], Context, VarSet, TVarSet) -->
- prog_out__write_context(Context),
- io__write_string(" "),
- mercury_output_var(Var, VarSet, no),
- io__write_string(" :: "),
- mercury_output_term(Type, TVarSet, no),
- io__write_string("\n"),
- write_type_var_list(Rest, Context, VarSet, TVarSet).
%-----------------------------------------------------------------------------%
Index: compiler/notes/compiler_design.html
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/notes/compiler_design.html,v
retrieving revision 1.12
diff -u -r1.12 compiler_design.html
--- compiler_design.html 1997/12/22 09:57:04 1.12
+++ compiler_design.html 1998/01/01 08:35:48
@@ -223,7 +223,8 @@
purity.m is responsible for purity checking, as well as
defining the <CODE>purity</CODE> type and a few public
operations on it. It also completes the handling of predicate
- overloading for cases which typecheck.m is unable to handle.
+ overloading for cases which typecheck.m is unable to handle,
+ and checks for unbound type variables.
<dt> mode analysis
Index: tests/invalid/errors2.err_exp
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/errors2.err_exp,v
retrieving revision 1.4
diff -u -r1.4 errors2.err_exp
--- errors2.err_exp 1997/06/29 23:24:37 1.4
+++ errors2.err_exp 1998/01/01 11:31:11
@@ -11,13 +11,6 @@
errors2.m:071: In clause for predicate `errors2:type_error_7/0':
errors2.m:071: warning: variables `Z, A, B' occur only once in this scope.
errors2.m:007: Error: no clauses for predicate `errors2:bind_type_param/2'
-errors2.m:018: In clause for predicate `errors2:unresolved_polymorphism/0':
-errors2.m:018: warning: unresolved polymorphism.
-errors2.m:018: The variables with unbound types were:
-errors2.m:018: V_2 :: TypeParam
-errors2.m:018: Arg :: TypeParam
-errors2.m:018: The unbound type variable(s) will be implicitly
-errors2.m:018: bound to the builtin type `void'.
errors2.m:023: Error: no clauses for predicate `errors2:produce_string/1'
errors2.m:025: Error: no clauses for predicate `errors2:expect_int/1'
errors2.m:031: In clause for predicate `errors2:type_error/0':
@@ -61,4 +54,16 @@
errors2.m:078: In clause for predicate `errors2:type_error_8/0':
errors2.m:078: error: undefined predicate `from_char_list/2'.
errors2.m:009: Inferred :- pred bind_type_param(int).
+errors2.m:016: In predicate `errors2:unresolved_polymorphism/0':
+errors2.m:016: warning: unresolved polymorphism.
+errors2.m:016: The variables with unbound types were:
+errors2.m:016: V_2 :: TypeParam
+errors2.m:016: Arg :: TypeParam
+errors2.m:016: The unbound type variable(s) will be implicitly
+errors2.m:016: bound to the builtin type `void'.
+errors2.m:019: In clause for `unresolved_polymorphism':
+errors2.m:019: in argument 1 of call to predicate `errors2:bind_type_param/2':
+errors2.m:019: mode error: variable `Arg' has instantiatedness `free',
+errors2.m:019: expected instantiatedness was `ground'.
+errors2.m:009: Error: no mode declaration for predicate `errors2:bind_type_param/1'.
For more information, try recompiling with `-E'.
Index: tests/invalid/funcs_as_preds.err_exp
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/funcs_as_preds.err_exp,v
retrieving revision 1.3
diff -u -r1.3 funcs_as_preds.err_exp
--- funcs_as_preds.err_exp 1997/05/20 02:08:33 1.3
+++ funcs_as_preds.err_exp 1998/01/01 11:31:11
@@ -19,4 +19,7 @@
funcs_as_preds.m:021: Inferred :- func car((list:list((list:list(T))))) = (list:list(T)).
funcs_as_preds.m:024: Inferred :- func cdr((list:list(T))) = (list:list(T)).
funcs_as_preds.m:027: Inferred :- func cons(T, (list:list(T))) = (list:list(T)).
+funcs_as_preds.m:021: Inferred :- mode car(in) = out is det.
+funcs_as_preds.m:024: Inferred :- mode cdr(in) = out is det.
+funcs_as_preds.m:027: Inferred :- mode cons(in, in) = out is det.
For more information, try recompiling with `-E'.
Index: tests/valid/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/valid/Mmakefile,v
retrieving revision 1.4
diff -u -r1.4 Mmakefile
--- Mmakefile 1997/11/24 23:10:37 1.4
+++ Mmakefile 1998/01/01 08:09:43
@@ -77,6 +77,7 @@
type_inf_ambig_test.m \
undead_proc.m \
uniq_unify.m \
+ unbound_tvar_in_lambda.m \
unreachable_code.m \
unused_args_test2.m \
vn_float.m
Index: tests/valid/unbound_tvar_in_lambda.m
===================================================================
RCS file: unbound_tvar_in_lambda.m
diff -N unbound_tvar_in_lambda.m
--- /dev/null Fri Jan 2 10:59:21 1998
+++ unbound_tvar_in_lambda.m Thu Jan 1 19:06:53 1998
@@ -0,0 +1,40 @@
+:- module unbound_tvar_in_lambda.
+:- interface.
+:- import_module io.
+:- pred main(io__state::di, io__state::uo) is det.
+:- implementation.
+:- import_module list, int, std_util, require.
+
+%--------------------------------------------------------%
+
+:- type node(S, T)
+ ---> append(list(S), list(S), list(S)).
+
+:- type proof(N)
+ ---> node(N, proof(N))
+ ; assumed.
+
+:- type proof(S, T) == proof(node(S, T)).
+
+%--------------------------------------------------------%
+
+% Simple polymorphic examples
+
+:- pred append_w(list(S), list(S), list(S), proof(S, T)).
+:- mode append_w(in, in, out, out) is det.
+:- mode append_w(out, out, in, out) is multi.
+
+append_w([], Bs, Bs, node(append([], Bs, Bs), assumed)).
+append_w([A|As], Bs, [A|Cs], node(append([A|As], Bs, [A|Cs]), Proof)) :-
+ append_w(As, Bs, Cs, Proof).
+
+
+%--------------------------------------------------------%
+
+main -->
+ write_string("--- Start Proofs ---\n\n"),
+ { Pred = (pred(P1::out) is nondet :-
+ append_w([1,2,3,4], [5,6,7], _, P1)) },
+ io__write(Pred),
+ write_string("--- End Proofs ---\n\n").
+
Index: tests/warnings/singleton_test.exp
===================================================================
RCS file: /home/mercury1/repository/tests/warnings/singleton_test.exp,v
retrieving revision 1.4
diff -u -r1.4 singleton_test.exp
--- singleton_test.exp 1997/04/29 10:57:06 1.4
+++ singleton_test.exp 1998/01/01 23:49:03
@@ -10,10 +10,10 @@
singleton_test.m:033: warning: variable `X' does not occur in the C code.
singleton_test.m:039: In `:- pragma c_code' for predicate `singleton_test:c_hello_world/3':
singleton_test.m:039: warning: variable `Msg' does not occur in the C code.
-singleton_test.m:027: In clause for function `singleton_test:my_append_func/2':
-singleton_test.m:027: warning: unresolved polymorphism.
-singleton_test.m:027: The variables with unbound types were:
-singleton_test.m:027: L2 :: V_2
-singleton_test.m:027: L1 :: V_2
-singleton_test.m:027: The unbound type variable(s) will be implicitly
-singleton_test.m:027: bound to the builtin type `void'.
+singleton_test.m:008: In function `singleton_test:my_append_func/2':
+singleton_test.m:008: warning: unresolved polymorphism.
+singleton_test.m:008: The variables with unbound types were:
+singleton_test.m:008: L2 :: V_1
+singleton_test.m:008: L1 :: V_1
+singleton_test.m:008: The unbound type variable(s) will be implicitly
+singleton_test.m:008: bound to the builtin type `void'.
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3 | -- the last words of T. S. Garp.
More information about the developers
mailing list