@@ -88,6 +88,7 @@ considered incompatible.
8888 * [ Minor: generalizing a function to use generics (supporting original type)] ( #fn-generalize-compatible )
8989 * [ Major: generalizing a function to use generics with type mismatch] ( #fn-generalize-mismatch )
9090 * [ Minor: making an ` unsafe ` function safe] ( #fn-unsafe-safe )
91+ * [ Major: adding a potentially shadowing method] ( #fn-add-potentially-shadowing-method )
9192 * Attributes
9293 * [ Major: switching from ` no_std ` support to requiring ` std ` ] ( #attr-no-std-to-std )
9394 * [ Major: adding ` non_exhaustive ` to an existing enum, variant, or struct with no private fields] ( #attr-adding-non-exhaustive )
@@ -1883,6 +1884,128 @@ Making a previously `unsafe` associated function or method on structs / enums
18831884safe is also a minor change, while the same is not true for associated
18841885function on traits (see [ any change to trait item signatures] ( #trait-item-signature ) ).
18851886
1887+ ### Major: add a potentially shadowing method {#fn-add-potentially-shadowing-method}
1888+
1889+ If you have a type which implements ` Deref<Target=T> ` , you must not add methods
1890+ which may "shadow" methods in ` T ` . This can lead to unexpected changes in
1891+ program behavior.
1892+
1893+ ``` rust,ignore
1894+ ///////////////////////////////////////////////////////////
1895+ // Before
1896+ pub struct MySmartPtr<T>(T);
1897+
1898+ impl<T> core::ops::Deref for MySmartPtr<T> {
1899+ type Target = T;
1900+ fn deref(&self) -> &Self::Target {
1901+ &self.0
1902+ }
1903+ }
1904+
1905+ ///////////////////////////////////////////////////////////
1906+ // After
1907+ pub struct MySmartPtr<T>(T);
1908+
1909+ impl<T> core::ops::Deref for MySmartPtr<T> {
1910+ type Target = T;
1911+ fn deref(&self) -> &Self::Target {
1912+ &self.0
1913+ }
1914+ }
1915+
1916+ impl<T> MySmartPtr<T> {
1917+ fn method(&mut self) {
1918+ println!("A");
1919+ }
1920+ }
1921+
1922+ ///////////////////////////////////////////////////////////
1923+ // Example usage that will break.
1924+ struct SomeStruct;
1925+
1926+ impl SomeStruct {
1927+ fn method(&self) {
1928+ println!("B");
1929+ }
1930+ }
1931+
1932+ fn main() {
1933+ let mut ptr = MySmartPtr(SomeStruct);
1934+ ptr.method(); // prints B before, A after
1935+ }
1936+ ```
1937+
1938+ Note that the shadowing and shadowed methods receive ` self `
1939+ slightly differently: ` &self ` and ` &mut self ` .
1940+ That's because Rust searches for methods first by value, then by ` & ` , then
1941+ by ` &mut T ` , then by ` *const T ` . Rust stops the search
1942+ when it encounters a valid method, and so methods later in this order may
1943+ be shadowed by methods encountered earlier.
1944+
1945+ This is only a compatibility risk if the ` Deref ` target is
1946+ beyond your control. If your type implements ` Deref ` to another type where
1947+ you can fix the available methods, you can ensure no shadowing
1948+ occurs. An example is that ` PathBuf ` implements
1949+ ` Deref<Target=Path> ` .
1950+
1951+ For types which do implement ` Deref ` with an arbitrary target,
1952+ it's bad practice to add methods: add associated functions instead. This is
1953+ the pattern used by Rust's standard library smart pointer types, such as
1954+ ` Box ` , ` Rc ` and ` Arc ` .
1955+
1956+ Similar shadowing risks occur for a type implementing
1957+ ` Receiver<Target=T> ` . If you have a type which implements either
1958+ ` Receiver<Target=T> ` or ` Deref<Target=T> ` it may be used as a method receiver
1959+ by ` T ` 's methods. If your type then adds a method, you may shadow methods in
1960+ ` T ` . For instance:
1961+
1962+ ``` rust,ignore
1963+ // MAJOR CHANGE
1964+
1965+ ///////////////////////////////////////////////////////////
1966+ // Before
1967+ pub struct MySmartPtr<T>(T);
1968+
1969+ impl<T> core::ops::Receiver for MySmartPtr<T> { // or Deref
1970+ type Target = T;
1971+ }
1972+
1973+ ///////////////////////////////////////////////////////////
1974+ // After
1975+ pub struct MySmartPtr<T>(T);
1976+
1977+ impl<T> core::ops::Receiver for MySmartPtr<T> { // or Deref
1978+ type Target = T;
1979+ }
1980+
1981+ impl<T> MySmartPtr<T> {
1982+ fn method(self) {
1983+
1984+ }
1985+ }
1986+
1987+ ///////////////////////////////////////////////////////////
1988+ // Example usage that will break.
1989+ struct SomeStruct;
1990+
1991+ impl SomeStruct {
1992+ fn method(self: &MySmartPtr<Self>) {
1993+
1994+ }
1995+ }
1996+
1997+ fn main() {
1998+ let ptr = MySmartPtr(SomeStruct);
1999+ ptr.method(); // error: multiple applicable items in scope
2000+ }
2001+ ```
2002+
2003+ When types like this are being used as method receivers, Rust endeavours to
2004+ do additional searches and present errors in simple cases, e.g. shadowing of
2005+ ` &self ` by ` self ` with inherent methods. This is better than invisible
2006+ behavior changes - but either way it's a compatibility break. Avoid adding
2007+ methods if you implement ` Deref ` or ` Receiver ` to an arbitrary target.
2008+
18862009### Major: switching from ` no_std ` support to requiring ` std ` {#attr-no-std-to-std}
18872010
18882011If your library specifically supports a [ ` no_std ` ] environment, it is a
0 commit comments