Resolve multi-candidate methods on impls defined outside the type's module - #4778
Open
kasimte wants to merge 1 commit into
Open
Resolve multi-candidate methods on impls defined outside the type's module#4778kasimte wants to merge 1 commit into
kasimte wants to merge 1 commit into
Conversation
…odule resolve_in_type_def refines multiple same-named inherent-impl candidates by comparing the user's turbofish generic arguments against the last two ::-separated segments of def_path_str(candidate). When a candidate's impl block lives in a different module than its self type, def_path_str renders it as `path::to::module::<impl path::to::Type<Args>>::method` instead of `Type::<Args>::method`, and no user-spellable turbofish can match that <impl ...> wrapper. Real instance: Box<dyn Any(+Send)(+Sync), A>::downcast_unchecked's three impls live in alloc/src/boxed/convert.rs while Box is defined in boxed.rs. Add a fallback in last_two_items_of_path_match: when the direct comparison fails and the candidate's second-to-last path segment is in <impl SELF_TYPE> form, extract SELF_TYPE's own generic arguments and retry the comparison against those. The retry strips the redundant parens def_path_str adds around a trait-object bound in a generic-argument list (e.g. `(dyn Any + 'static)` -> `dyn Any + 'static`) before comparing; tuple-type parens are semantic and preserved.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Resolves #4777.
last_two_items_of_path_matchcompares the user's turbofish againstdef_path_str's rendering of each candidate. Impls living outside their type's home module render as<impl Type<Args>>, which no user-spellable path can equal — so multi-candidate methods in that position (e.g. the threeBox<dyn Any(+Send)(+Sync), A>::downcast_uncheckedimpls in alloc'sboxed/convert.rs) fail to resolve under every spelling, while single-candidate methods skip refinement and work.This is the out-of-module half of #3773 (whose fix and
multiple_inherent_impls.rstest cover the same-module rendering). It adds a fallback that unwraps the<impl SELF_TYPE>form, extracts SELF_TYPE's generic arguments, strips the disambiguation parenthesesdef_path_stradds around trait-object bounds (tuple-type parentheses are semantic and preserved), and retries the comparison.Scope: this keeps the existing string-comparison approach and only unblocks the out-of-module rendering; the milder same-module symptom (concrete turbofish arguments not matching a structured self-type such as
MaybeUninit<u32>vs the impl'sMaybeUninit<T>— the generic-parameter spelling works there) is unchanged, and a semantic-resolution rewrite would subsume both. Happy to take direction if the deeper rewrite is preferred.Tests: four unit tests in the existing
simple_last_two_items_of_path_matchmodule (dyn-args match + mismatch, tuple parens preserved, non-generic no-fallback) and a new end-to-end regression testtests/kani/FunctionContracts/cross_module_multiple_impls.rs(fails to resolve before the fix, verifies after). Also validated on the motivating case: all threeBox<dyn Any…>::downcast_uncheckedcontracts in verify-rust-std resolve and verify asproof_for_contracttargets under the patched resolver.Applies cleanly on current
main(last_two_items_of_path_matchis unchanged there). One call-out: candidates whose rendered path contains->(fn-pointer /Fn-sugar types) are not unwrapped by the fallback's bracket counting — they keep the existing failed-to-resolve behavior rather than matching a different candidate.Motivating case: model-checking/verify-rust-std#669 — the three
Box<dyn Any…>::downcast_uncheckedcontract targets there.By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.