Remove erroneous optimization from eqtype#13306
Conversation
|
I agree that mixing the equalities of |
|
It turns out that the physical equality check is necessary when |
|
We could also handle the variable case directly: | (Tvar _, Tvar _) ->
if rename then eqtype_subst type_pairs subst t1 t2
else if eq_type t1 t2 then ()
else raise_unexplained_for EqualityBut I agree that using the representative physical equality is correct without renaming and faster. |
|
I am also wondering if we want to add a short-circuit test in let equal env rename tyl1 tyl2 =
if not rename && List.for_all2 eq_type tyl1 tyl2 then () else
let subst = ref [] in
try eqtype_list rename (TypePairs.create 11) subst env tyl1 tyl2
with Equality_trace trace ->
raise (Equality (expand_to_equality_error env trace !subst))under the hypothesis that the optimisation is safe and could trigger not that infrequently in this location. |
If [eqtype] no longer assumes separation, then [Printtyp.Names] shouldn't either.
typing/ctype.ml
Outdated
| let equal env rename tyl1 tyl2 = | ||
| if List.length tyl1 <> List.length tyl2 then | ||
| raise_unexplained_for Equality; | ||
| if not rename && List.for_all2 eq_type tyl1 tyl2 then () else |
There was a problem hiding this comment.
Since there are no substitution in scope at this point, the not rename guard should not be needed, isn't it? If tyl1 and tyl2 are physically equal, they will be equal with the trivial substitution.
|
After the explanation, I think I understand the problem, and why it doesn't happen in practice. |
Co-authored-by: Gabriel Scherer <gabriel.scherer@gmail.com>
| let substitute ty = | ||
| match List.assq ty !name_subst with | ||
| | ty' -> substitute ty' | ||
| | ty' -> ty' |
There was a problem hiding this comment.
This is a fix, but the commit message seems inexact to me:
- with separation, the inner substitute always falls because variables on the right side never appear on the left side
- without separation the previous call is mixing the two sides and deciding that
'a * 'b * int='b * 'c * float, the left hand side should be displayed as'c * ' c * intis not equal to'c * 'c * floatrather than'b * 'c * intis not equal to'b * 'c * float.
There was a problem hiding this comment.
Without separation, it's even worse: the previous call could loop infinitely. (Indeed I observed this in my branch that does not enforce separation.) Thus my claim that dropping this recursion removes the separation assumption. And, in any case, it seems unnecessary.
There was a problem hiding this comment.
Yes, I agree that the function call is either unnecessary (with the separation hypothesis) or wrong. I am just not sure I would describe the current call as a "use of the separation assumption".
Octachron
left a comment
There was a problem hiding this comment.
The current state looks ready to merge, and I think it is good to simplify preconditions in this part of the typechecker.
|
During our discussion today I had the impression that it is not obvious to everyone that |
From the top of
Ctype.eqtype, I've removed a call toeq_typeand added this comment:See if you agree with the comment.
There is no known actual bug that this fixes, and thus no test case. But I'm doing some other work around here in the Jane Street branch, and the check is causing problems in that context.