-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Refactored check::autoderef
in librustc_typeck
to allow additional behaviour upon reaching the recursion limit
#28931
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @brson (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. The way Github handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
This looks like it makes autoderef's non-deterministic (or at least very sensitive to the number of available derefs)? |
In the case of method derefing it does preserve the order in which it is derefeered. If this would cause non deterministic behavior, so would having more than one fitting type in the hierachie, wouldnt it? (actual question) |
Intentionally hitting the recursion limit seems like a bad idea: it will hurt rustc's performance on code which uses constructs like this, and depending on the recursion limit as part of the non-error control flow is confusing. |
The other option - checking after each iteration if we already found the current type, scales much worse though. While simply relying on the recursion limit terminates after O(n), with n being the recursion limit in case of a cycle, the other option require (n(n+1))/2 checks, which scales with O(n^2), n being the size of the cycle + the head leading into it. |
r? @pnkfelix |
To be fair, I tried to implement the cycle-detecting variant as well. And it seems less intrusive, than this one, even though it scales worse. I'd be able to make another PR with that variant, if prefered. (I wouldn't need to change the The performance depends pretty heavily on the size of the cycles, so I'm not really sure which would be the better one. |
@@ -2099,6 +2099,19 @@ pub enum UnresolvedTypeAction { | |||
Ignore | |||
} | |||
|
|||
/// Desired behaviour upon reaching the recursion limit. Used in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yay docs!
@skeleten based on niko's feedback on the other bug, I'm hesitant to immediately In particular, it sounds to me like @nikomatsakis thinks the strategy you've used here is too fragile. You mentioned that cycle-detection doesn't scale well. (I assume by that you mean that it adds more overhead to the compilation time compared to this change.) Couldn't we cope with that by starting to do the cycle detection only after we've hit some initial work threshold? I.e., once That is, as I understand what others are saying: if you can prove that a cycle actually exists, then it might be sound to cut short the candidate expansion. But in the absence of such proof, continue to error upon hitting the recursion limit? Having said that, I'm going to ping @nikomatsakis and ask him what he thinks about the options here. |
The actual performance overhead is very dependent on the |
handing review off to @nikomatsakis for further discussion/decisions |
It seems that triage has decided to detect cycls, making this implementation (and therefore PR) obsolete, so I'll close this here :) |
Fixes bug #19509
In this bug, it relied for the
autoderef
method to terminate once it reaches a non-deref-able type and collecting all types before selecting the appropiate type.However, if there were cycles in the deref-types this would never happen and instead the function would hit its recursion limit resulting in an error, even if an apropiate type could've been found within the recursion limit.
This change refactores
autoderef
into another functionautoderef_with_recursion_option
and adding an additonal parameter describing the behaviour upon reaching the recursion limit.The
autoderef
function callsautoderef_with_recursion_option
with the default behaviour (error gracefully) while the problemsome function calls it with an option allowing it to not error, but return the last found type.Another approach would've been to detect cycles directly by comparing it to a list of already checked types, however this would most likely have added more overhead.