@@ -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,136 @@ 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,run-fail
1894+ // MAJOR CHANGE
1895+
1896+ ///////////////////////////////////////////////////////////
1897+ // Before
1898+ #[derive(Clone, Copy)]
1899+ pub struct MySmartPtr<T>(pub T);
1900+
1901+ impl<T> core::ops::Deref for MySmartPtr<T> {
1902+ type Target = T;
1903+ fn deref(&self) -> &Self::Target {
1904+ &self.0
1905+ }
1906+ }
1907+
1908+ ///////////////////////////////////////////////////////////
1909+ // After
1910+ #[derive(Clone, Copy)]
1911+ pub struct MySmartPtr<T>(pub T);
1912+
1913+ impl<T> core::ops::Deref for MySmartPtr<T> {
1914+ type Target = T;
1915+ fn deref(&self) -> &Self::Target {
1916+ &self.0
1917+ }
1918+ }
1919+
1920+ impl<T> MySmartPtr<T> {
1921+ pub fn method(self) -> usize {
1922+ 2
1923+ }
1924+ }
1925+
1926+ ///////////////////////////////////////////////////////////
1927+ // Example usage that will break.
1928+ use updated_crate::MySmartPtr;
1929+
1930+ struct SomeStruct;
1931+
1932+ impl SomeStruct {
1933+ fn method(&self) -> usize {
1934+ 1
1935+ }
1936+ }
1937+
1938+ fn main() {
1939+ let mut ptr = MySmartPtr(SomeStruct);
1940+ assert_eq!(ptr.method(), 1);
1941+ }
1942+ ```
1943+
1944+ Note that the shadowing and shadowed methods receive ` self `
1945+ slightly differently: ` self ` and ` &self ` .
1946+ That's because Rust [ searches for methods] first by value, then by ` & ` , then
1947+ by ` &mut T ` . Rust stops the search when it encounters a valid method, and
1948+ so methods later in this order may be shadowed by methods encountered earlier.
1949+
1950+ This is only a compatibility risk if the ` Deref ` target is
1951+ beyond your control. If your type implements ` Deref ` to another type where
1952+ you can fix the available methods, you can ensure no shadowing
1953+ occurs. An example is that ` PathBuf ` implements
1954+ ` Deref<Target=Path> ` .
1955+
1956+ For types which do implement ` Deref ` with an arbitrary target,
1957+ it's bad practice to add methods: add associated functions instead. This is
1958+ the pattern used by Rust's standard library smart pointer types, such as
1959+ ` Box ` , ` Rc ` and ` Arc ` .
1960+
1961+ Similar shadowing risks occur for a type implementing
1962+ ` Receiver<Target=T> ` . If you have a type which implements either
1963+ ` Receiver<Target=T> ` or ` Deref<Target=T> ` it may be used as a method receiver
1964+ by ` T ` 's methods. If your type then adds a method, you may shadow methods in
1965+ ` T ` . For instance:
1966+
1967+ ``` rust,ignore,skip
1968+ // MAJOR CHANGE
1969+
1970+ ///////////////////////////////////////////////////////////
1971+ // Before
1972+ #![feature(arbitrary_self_types)]
1973+ pub struct MySmartPtr<T>(pub T);
1974+
1975+ impl<T> core::ops::Receiver for MySmartPtr<T> {
1976+ // or Deref
1977+ type Target = T;
1978+ }
1979+
1980+ ///////////////////////////////////////////////////////////
1981+ // After
1982+ #![feature(arbitrary_self_types)]
1983+ pub struct MySmartPtr<T>(pub T);
1984+
1985+ impl<T> core::ops::Receiver for MySmartPtr<T> {
1986+ // or Deref
1987+ type Target = T;
1988+ }
1989+
1990+ impl<T> MySmartPtr<T> {
1991+ pub fn method(self) {}
1992+ }
1993+
1994+ ///////////////////////////////////////////////////////////
1995+ // Example usage that will break.
1996+ #![feature(arbitrary_self_types)]
1997+ use updated_crate::MySmartPtr;
1998+
1999+ struct SomeStruct;
2000+
2001+ impl SomeStruct {
2002+ fn method(self: &MySmartPtr<Self>) {}
2003+ }
2004+
2005+ fn main() {
2006+ let ptr = MySmartPtr(SomeStruct);
2007+ ptr.method(); // Error: multiple applicable items in scope
2008+ }
2009+ ```
2010+
2011+ When types like this are being used as method receivers, Rust endeavours to
2012+ do additional searches and present errors in simple cases, e.g. shadowing of
2013+ ` &self ` by ` self ` with inherent methods. This is better than invisible
2014+ behavior changes - but either way it's a compatibility break. Avoid adding
2015+ methods if you implement ` Deref ` or ` Receiver ` to an arbitrary target.
2016+
18862017### Major: switching from ` no_std ` support to requiring ` std ` {#attr-no-std-to-std}
18872018
18882019If your library specifically supports a [ ` no_std ` ] environment, it is a
@@ -2317,3 +2448,4 @@ document what your commitments are.
23172448[ wildcard patterns ] : ../../reference/patterns.html#wildcard-pattern
23182449[ unused_unsafe ] : ../../rustc/lints/listing/warn-by-default.html#unused-unsafe
23192450[ msrv-is-minor ] : https://github.com/rust-lang/api-guidelines/discussions/231
2451+ [ searches for methods ] : ../../reference/expressions/method-call-expr.html#method-call-expressions
0 commit comments