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
{{ message }}
Repository navigation
Experiment with tracking which entities actually may be narrowed #51525
In Pyright, narrowing can be avoided by keeping track of which entities actually get narrowed within a given scope. This could save a good amount of time by avoiding redundant walks up the control flow graph just to discover nothing interesting a given variable or property.
I'm not sure if Pyright also tracks the first location at which an entity may be narrowed, but that information could also be used to signal when a narrowing walk needs to stop.
This would come at the cost of some memory overhead, but we'd need to experiment to see what the trade-offs are.
Wait, does TS walk the control flow graph backwards to discover narrowings? I always figured the graph looked something like x = string | number -> if (true) x = string -> else x = number and the compiler would know exactly which part of the tree it was in at the time it encountered a reference to x so it could just look up the current type directly.
It does walk backwards. If it walked forwards, it would have to retain the context of all potential narrowing operations (and for all potential types we'd want to narrow from - which is occasionally necessary for things like narrowing constraints of generics rather than the generics themselves). That wouldn't work in our system where checking an expression should be as lazy as possible.
Anyway, in line with that, there are definitely opportunities for us to optimize here.
I guess that makes sense now that I think about it - there really aren't any "set the type to string" style narrowings - even typeof x === 'string' can narrow to never if the original type doesn't overlap with string. Otherwise you could probably do some kind of short-circuiting logic.
Activity
jakebailey commentedon Nov 14, 2022
I think the code in question for pyright was introduced in:
fatcerberus commentedon Nov 14, 2022
Wait, does TS walk the control flow graph backwards to discover narrowings? I always figured the graph looked something like
x = string | number->if (true) x = string->else x = numberand the compiler would know exactly which part of the tree it was in at the time it encountered a reference toxso it could just look up the current type directly.DanielRosenwasser commentedon Nov 14, 2022
It does walk backwards. If it walked forwards, it would have to retain the context of all potential narrowing operations (and for all potential types we'd want to narrow from - which is occasionally necessary for things like narrowing constraints of generics rather than the generics themselves). That wouldn't work in our system where checking an expression should be as lazy as possible.
Anyway, in line with that, there are definitely opportunities for us to optimize here.
fatcerberus commentedon Nov 14, 2022
I guess that makes sense now that I think about it - there really aren't any "set the type to
string" style narrowings - eventypeof x === 'string'can narrow toneverif the original type doesn't overlap withstring. Otherwise you could probably do some kind of short-circuiting logic.Port pyright optimization that skips loop flow nodes that dont contai…