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
Types implementing Deref, e.g. Rc<T>, can shadow methods of their target types. This can happen in two ways:
either by the impl of both types defining the same method (case A)
or by the method being added to either of the types via a trait (cases B and C).
While this is according to the intended Deref design, it can easily lead to confusion or bugs. It is also one case where adding impls or importing traits can silently change behavior (see below) or break the code (see e.g. #41906 and the original #41865).
We should be able to detect it and at least issue a warning.
Details and illustration
To illustrate, consider this code excerpt (full playpen). (The types here are abstract on purpose, but see #41906 and case C below for examples with Borrow.)
Case A is triggered by adding impl<T> A<T> { fn method(&self) { } }. While here the behavior is least confusing of the three, it still a bad design we might be able to detect and warn about. (This is the reason Deref types such as std::rc::Rc generally only have type-associated methods.)
Case B is triggered by implementing a trait with method on A<T> as below. This is harder to both avoid (trait methods are not associated) and notice.
Case C is triggered similarly to B, by the code below. The difference is that the trait is implemented in another module and only gets activated by an use.
mod sub {pubtraitHidden{fnmethod(&self){println!("Hidden::method");}}impl<T>Hiddenforsuper::A<T>{}}use sub::Hidden;
For this last case, I have a slightly more realistic example with use std::borrow::Borrow; triggering a different behavior with no warnings. See the playpen.
Solution
On a method call, we could inspect the entire Deref chain of types for methods of the same name and issue a warning if we find a method of the same name.
Users could resolve this with:
Explicit deref and call: (*a).method()
Explicit call without deref: A::method(&a)
Some #[allow(deref_shadowing)] pragma
I would see this as an important warning: activating any two of the cases A, B or C at once is a compiler error (as it should be) and the Deref coercion is very close to that from user point of view but gives no warning.
This would also resolve #41906 in a general way (are there any other related issues?)
The text was updated successfully, but these errors were encountered:
Types implementing
Deref
, e.g.Rc<T>
, can shadow methods of their target types. This can happen in two ways:impl
of both types defining the same method (case A)While this is according to the intended
Deref
design, it can easily lead to confusion or bugs. It is also one case where addingimpl
s or importing traits can silently change behavior (see below) or break the code (see e.g. #41906 and the original #41865).We should be able to detect it and at least issue a warning.
Details and illustration
To illustrate, consider this code excerpt (full playpen). (The types here are abstract on purpose, but see #41906 and case C below for examples with
Borrow
.)Case A is triggered by adding
impl<T> A<T> { fn method(&self) { } }
. While here the behavior is least confusing of the three, it still a bad design we might be able to detect and warn about. (This is the reasonDeref
types such asstd::rc::Rc
generally only have type-associated methods.)Case B is triggered by implementing a trait with
method
onA<T>
as below. This is harder to both avoid (trait methods are not associated) and notice.Case C is triggered similarly to B, by the code below. The difference is that the trait is implemented in another module and only gets activated by an
use
.For this last case, I have a slightly more realistic example with
use std::borrow::Borrow;
triggering a different behavior with no warnings. See the playpen.Solution
On a method call, we could inspect the entire
Deref
chain of types for methods of the same name and issue a warning if we find a method of the same name.Users could resolve this with:
(*a).method()
A::method(&a)
#[allow(deref_shadowing)]
pragmaI would see this as an important warning: activating any two of the cases A, B or C at once is a compiler error (as it should be) and the
Deref
coercion is very close to that from user point of view but gives no warning.This would also resolve #41906 in a general way (are there any other related issues?)
The text was updated successfully, but these errors were encountered: