Typing_env_level.join_types: use correct typing env #329
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There is an issue during
Typing_env_level.join_types
where the environment used for the accumulated equations is wrong.Here is how the code works, on the following example inputs (in this case the result is correct even without this patch though):
The aim of this function is to compute a map of equations that are a sound approximation of the equations of each input.
In this case, one possible result would be:
However, other correct but less precise results can be returned too.
Because the number of uses can be arbitrary, the join is not done between two inputs but instead built by folding on the list of uses, accumulating the result so far. So in practice we will have two steps:
Use 1
, producingJoin 1
Join 1
withUse 2
, producing the final result.All of this is not changed by this patch.
However, to be able to join types, we need an environment in which they are valid. For the empty map, the original
env_at_fork
works (it's actually used even if the map is empty). For each of the uses, we have a correspondingenv_at_use
that we can use (for some reason, in one placeenv_at_fork
was used instead. I'm not convinced by the comment justifying this, and chose to useenv_at_use
as it's more coherent). The problem is in having an environment for the partial results (likeJoin 1
earlier).Before the patch, this environment was computed along the result equations by accumulation: starting from
env_at_fork
for the empty equations, for the following steps environments are computed by first resolving which equations will end up in the joined types (with all joins done using the accumulated environment at the start of the step), and then adding all those equations to the environment that we had at the start of the step; the resulting environment will be used for the next step.There are two main problems with this approach:
Typing_env.add_equation
being able to replace an existing equation with a less precise one. This isn't even actually ensured in all cases by the code ofadd_equation
, but the fact that in some cases it was still possible to lose information by doingadd_equation
was already problematic in a number of other places so in Better extension from meet #316Typing_env.add_equation
always meets with the current type if any. This means it is not suitable for this particular case anymore, so I had to patch this part of the code.Typing_env.t
not all information is held in the equations. The aliases part of the structure also contain information, and this information is not removed if an equation (say,x : (= 0)
) is replaced by another (x : {0, 1}
). This means that the result is an environment wherex
has type{0, 1}
but is known from the aliases to be equal to0
.To fix this, this patch simply re-computes at each step a suitable environment for the join functions. Starting from
env_at_fork
, the equations from the accumulator (joined_types
in the code) are added to this environment using aTyping_env_extension
, which yields an environment in which the equations fromjoined_types
are valid. This environment is discarded at the end of the step and a new one is created for the next step.This avoids both problems: the first because we're never trying to forget equations so we don't need to rely on a replace semantics for
add_equation
, and the second one because since we start fromenv_at_fork
at each step the only aliases we will have are the ones coming fromenv_at_fork
(which are always valid in all branches) and the ones that are created by thejoined_types
.