fix: Improve hygiene of trait impl macros#839
Merged
RobertJacobsonCDC merged 1 commit intomainfrom Apr 7, 2026
Merged
Conversation
…o-based trait impls where name collisions with methods on the concrete type are possible
Benchmark ResultsHyperfine
CriterionRegressions (slower)
Improvements (faster)
Unchanged / inconclusive (CI crosses 0%)
|
k88hudson-cfa
approved these changes
Apr 7, 2026
Collaborator
k88hudson-cfa
left a comment
There was a problem hiding this comment.
Looks good to me, it does make me wonder if this happens elsewhere in the codebase?
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.
This PR improves the hygiene of macros that call trait methods on concrete types. Since we are touching this macro code anyway, we also normalize a particular syntax we use in macro definitions (described below), which is merely cosmetic and has no functional effect.
Use fully qualified trait method invocation in macro-generated trait impls when name collisions are possible
Suppose we have a macro that implements a trait for a concrete type identified by a macro parameter like
$identifier, and that same macro also generates code that calls methods from that trait on that type. If those generated calls use ordinary syntax like$identifier::id()or$identifier::is_derived(), they can collide with inherent methods already defined on the concrete type. For example, if the macro implementsProperty<Person>forAge, andAgealready has its own inherentfn id() -> usize, then generated code that saysAge::id()may call the inherent method instead of the trait methodProperty<Person>::id(). And ifAge::id()has a different signature fromProperty<Person>::id(), you get a compiler error.We fix this by changing such calls to fully qualified trait method syntax, so the generated code explicitly names both the trait and the receiver type. Instead of generating
$identifier::id()or$identifier::is_derived(), we generate calls like<$identifier as $crate::entity::property::Property<$entity>>::id()and<$identifier as $crate::entity::property::Property<$entity>>::is_derived(). This removes the ambiguity by telling Rust exactly which trait method to call, even if the concrete type also defines an inherent method with the same name.This is motivated by the real example of trying to implement
Property<Person>forFIPSCode, because the concrete type has a methodFIPSCode::idthat collides withProperty::id.Use consistent syntax for
Selfin fully qualified trait method invocationThis PR also normalizes fully qualified trait method calls so that, whenever the receiver is the current impl type, we write
Selfinstead of repeating the concrete type name. For example, insrc/macros/property_impl.rswe use<Self as $crate::entity::property::Property<$entity>>::id()rather than<$property as $crate::entity::property::Property<$entity>>::id().The justification for this is:
Selfavoids having to restate type parameters, lifetimes, and wrappers in the qualified path. That makes the macro simpler and less fragile.Selfkeeps the call correct without needing to update repeated type syntax.<Self as Trait>::...reads as "call the trait method from this impl."This isn't a very important change, but it is also pretty low risk. Syntactic housekeeping since we are touching the code anyway.