You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Part of the problem in talking about this issue is that we don't have great terminology,
so I'm gonna use some terminology that I think is reasonable, but we should probably
come up with some proper names for all these concepts and put them in the devdocs.
Consider a call cycle like
+------------+
v +
E+>A+>B+>C+>B'+>D->E'
^
F+-+
Where B, B' are the same method with different signatures, (as are E and E').
Now, when inference see a method cycle like B->B' it has some heuristics to
decide whether to allow this or whether to "limit" the signature B' (e.g. by widening
some arguments to Any to force it to have strictly less information than B, thus
preventing infinitely growing types). However, when it does this it must also
"poison" all inference frames between B and B' (in this case C) to avoid
caching it. This is done such that if some other caller enters C, (without having
gone through B), it will not be subject to the same limiting.
Now, in the example above, we later discover that C is actually part of the
SCC (strongly-connected component) A,B,C,B',D. In this case, we should
be able to undo the limiting, because any entry point into the SCC will always
eventually see the B->B' method cycle forcing limiting. However, we need
to be a bit careful, because we could also be in the situation E->SCC->E'
in which case the entire SCC does actually need to be poisoned to avoid
pessimizing inference for F->SCC->E'.
Currently we only track a boolean for the limited flag, which is insufficient to
distinguish the above two cases. We should extend this information to track
which limiting decisions the current results depend on, then figuring out if
they are part of the current SCC or not.
As an additional refinement, we could also clear any limiting decisions that
don't actually affect the return value of the current function.
Yeah I recall looking at a case with Peter where having a A -> B -> A disabled the normal self-recursion heuristic, which limited the kind of codes we could write, before having to use @generated as an escape hatch. So I am all in favor of handling this.
Part of the problem in talking about this issue is that we don't have great terminology,
so I'm gonna use some terminology that I think is reasonable, but we should probably
come up with some proper names for all these concepts and put them in the devdocs.
Consider a call cycle like
Where
B
,B'
are the same method with different signatures, (as areE
andE'
).Now, when inference see a method cycle like
B
->B'
it has some heuristics todecide whether to allow this or whether to "limit" the signature
B'
(e.g. by wideningsome arguments to
Any
to force it to have strictly less information thanB
, thuspreventing infinitely growing types). However, when it does this it must also
"poison" all inference frames between
B
andB'
(in this caseC
) to avoidcaching it. This is done such that if some other caller enters
C
, (without havinggone through
B
), it will not be subject to the same limiting.Now, in the example above, we later discover that
C
is actually part of theSCC (strongly-connected component)
A,B,C,B',D
. In this case, we shouldbe able to undo the limiting, because any entry point into the SCC will always
eventually see the
B->B'
method cycle forcing limiting. However, we needto be a bit careful, because we could also be in the situation
E->SCC->E'
in which case the entire SCC does actually need to be poisoned to avoid
pessimizing inference for
F->SCC->E'
.Currently we only track a boolean for the
limited
flag, which is insufficient todistinguish the above two cases. We should extend this information to track
which limiting decisions the current results depend on, then figuring out if
they are part of the current SCC or not.
As an additional refinement, we could also clear any limiting decisions that
don't actually affect the return value of the current function.
cc @NHDaly @Sacha0 @vtjnash
The text was updated successfully, but these errors were encountered: