@@ -1101,6 +1101,11 @@ pub struct Pin<Ptr> {
1101
1101
#[ unstable( feature = "unsafe_pin_internals" , issue = "none" ) ]
1102
1102
#[ doc( hidden) ]
1103
1103
pub __pointer : Ptr ,
1104
+
1105
+ /// See the docs of [`lifetime_extension`] for more info.
1106
+ #[ unstable( feature = "unsafe_pin_internals" , issue = "none" ) ]
1107
+ #[ doc( hidden) ]
1108
+ pub __phantom : crate :: marker:: PhantomData < Ptr > ,
1104
1109
}
1105
1110
1106
1111
// The following implementations aren't derived in order to avoid soundness
@@ -1355,7 +1360,7 @@ impl<Ptr: Deref> Pin<Ptr> {
1355
1360
#[ rustc_const_stable( feature = "const_pin" , since = "1.84.0" ) ]
1356
1361
#[ stable( feature = "pin" , since = "1.33.0" ) ]
1357
1362
pub const unsafe fn new_unchecked ( pointer : Ptr ) -> Pin < Ptr > {
1358
- Pin { __pointer : pointer }
1363
+ Pin { __pointer : pointer, __phantom : crate :: marker :: PhantomData }
1359
1364
}
1360
1365
1361
1366
/// Gets a shared reference to the pinned value this [`Pin`] points to.
@@ -1575,7 +1580,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> {
1575
1580
#[ rustc_const_stable( feature = "const_pin" , since = "1.84.0" ) ]
1576
1581
#[ stable( feature = "pin" , since = "1.33.0" ) ]
1577
1582
pub const fn into_ref ( self ) -> Pin < & ' a T > {
1578
- Pin { __pointer : self . __pointer }
1583
+ Pin { __pointer : self . __pointer , __phantom : crate :: marker :: PhantomData }
1579
1584
}
1580
1585
1581
1586
/// Gets a mutable reference to the data inside of this `Pin`.
@@ -2014,5 +2019,145 @@ pub macro pin($value:expr $(,)?) {
2014
2019
//
2015
2020
// See https://doc.rust-lang.org/1.58.1/reference/destructors.html#temporary-lifetime-extension
2016
2021
// for more info.
2017
- $crate:: pin:: Pin :: < & mut _ > { __pointer : & mut { $value } }
2022
+ $crate:: pin:: Pin :: < & mut _ > {
2023
+ __pointer : & mut $crate:: pin:: __Pinned {
2024
+ value_expression_preserving_lifespan_extension_of_temporaries : $value,
2025
+ } as & mut _ ,
2026
+ // ^^^^^^^^
2027
+ // DerefMut coërcion, because of --+
2028
+ __phantom : { // <------------------+
2029
+ let pin = $crate:: marker:: PhantomData ;
2030
+ if false {
2031
+ loop { }
2032
+ // We use dead code to disable move semantics (and borrowck) to allow us to refer to
2033
+ // `$value` again even when `$value` happens to consume non-`Copy` stuff or whatnot.
2034
+ #[ allow( unreachable_code) ] {
2035
+ $crate:: pin:: __phantomdata_set_typeof_pointee ( pin, $value) ;
2036
+ }
2037
+ }
2038
+ pin
2039
+ } ,
2040
+ }
2041
+ }
2042
+
2043
+ /// Since the 2024 edition, the rules for lifespan-of-temporaries extension have changed,
2044
+ /// and `{ $value }` no longer cuts it for all the scenarios where it did in the 2021 edition and
2045
+ /// before.
2046
+ ///
2047
+ /// - aside: throughout this documentation the expression "lifespan extension" shall be preferred
2048
+ /// to that of "lifetime extension", so as to clarify we are firstly talking of the lifespan of
2049
+ /// a temporary, which, when extended, results in the lifetime of a borrow to it to be allowed
2050
+ /// to be bigger. This nit seems more in line with the idea that lifetimes themselves are just
2051
+ /// descriptive, not prescriptive, so it does not make that much sense to talk of extending one
2052
+ /// _directly_. We would not need to lift this ambiguity had Rust chosen a term other than
2053
+ /// "lifetime" to talk of the duration of borrows.
2054
+ ///
2055
+ /// Indeed, things such as the following regressed:
2056
+ ///
2057
+ /// ```rust
2058
+ /// // Regression test for #138596
2059
+ ///
2060
+ /// fn main() {
2061
+ /// match core::pin::pin!(foo(&mut 0)) {
2062
+ /// _f => {}
2063
+ /// }
2064
+ /// }
2065
+ ///
2066
+ /// async fn foo(_s: &mut usize) {}
2067
+ /// ```
2068
+ ///
2069
+ /// The reason for that is that we'd end up with `{ foo(&mut temporary(0)) }` among the expansion
2070
+ /// of `pin!`, and since this happens in `match`-scrutinee position, temporaries get not to outlive
2071
+ /// their encompassing braced block(s), so `temporary(0)` dies before that `}`, and the resulting
2072
+ /// `Pin { … }` is born dangling.
2073
+ ///
2074
+ /// But we do need a _value expression_ behind our `Pin { __pointer: &mut`, lest Rust treat it as a
2075
+ /// _place expression_, and allow things such as `$value = *&mut non_unpin`, which would break
2076
+ /// the soundness requirement of `Pin` (see
2077
+ /// https://github.com/rust-lang/rust/issues/138596#issuecomment-2729894350).
2078
+ ///
2079
+ /// This naïvely leaves us with things such as `identity($value)` or `($value, ).0` as
2080
+ /// plausible alternatives.
2081
+ ///
2082
+ /// But, alas, this now breaks the lifespan-of-temps extension happening _inside of `$value`_, which
2083
+ /// has been an accidental, but stabilized and quite convenient, property of `pin!`.
2084
+ /// For instance, the following code would break:
2085
+ ///
2086
+ /// ```rust
2087
+ /// fn temporary() {}
2088
+ ///
2089
+ /// let p = core::pin::pin!(&mut temporary());
2090
+ /// let _some_usage_of_p = (&p, );
2091
+ /// ```
2092
+ ///
2093
+ /// And there are several occurrences of `pin!(&mut …)` in the wild, and whilst most of them are
2094
+ /// inlined/short usages of `Pin<&mut _>`, there is at least one instance of such code actually
2095
+ /// being multi-statement lived, and thus relying on the lifespan-of-temps extension property of
2096
+ /// `pin!()`.
2097
+ ///
2098
+ /// So, unless/until we get `pin!()` —or a helper inner macro thereof— to be using edition 2021
2099
+ /// rules for its `{ $value }` expression, the only 2024-edition-compatible workaround found so far
2100
+ /// hinges on the following observation:
2101
+ ///
2102
+ /// > `&mut Wrapper { field: $value }` happens to preserve the lifespan-of-temps-extending
2103
+ /// > rules of 2021 edition `&mut $value`, and also funnels `$value` through a value expression.
2104
+ ///
2105
+ /// But we get a `&mut Wrapper<typeof<$value>>` rather than a `&mut typeof<$value>`.
2106
+ /// So now the challenge is to get `DerefMut` to take place here, and we are good!
2107
+ ///
2108
+ /// Only…, so far, lifespan-extension rules get broken by _explicit_ `Deref{,Mut}` such as `*`,
2109
+ /// `&*`, or, in our case, `&mut *`!! 😩
2110
+ ///
2111
+ /// But…, it does not get broken by _implicit_ `Deref{,Mut}`, such as the one triggered by a deref
2112
+ /// coërcion!
2113
+ ///
2114
+ /// That is, `&mut Wrapper { field: $value } as &mut typeof<$value>` does preserve lifespan-of-temps
2115
+ /// extension!
2116
+ ///
2117
+ /// So, our final challenge now is to express `&mut typeof<$value>` when `typeof` is not available.
2118
+ ///
2119
+ /// The usual approach is
2120
+ /// `if false { /* unreachable code to infer type */ } else { /* real code */ }`, but we cannot
2121
+ /// do that either since the braced blocks here are the "same" as our originally problematic
2122
+ /// `{ $value }` to begin with!
2123
+ ///
2124
+ /// So the only remaining tool available to our disposable are the very fields of `Pin { … }`: we
2125
+ /// can have an extra `PhantomData` field, which "redundantly" uses the `Ptr` type, thereby
2126
+ /// introducing a type equality constraint between the two fields similar to that of an `if … else`,
2127
+ /// and which is where we shall be able to insert our `/* unreachable code to infer type */`.
2128
+ #[ doc( hidden) ]
2129
+ #[ unstable( feature = "unsafe_pin_internals" , issue = "none" ) ]
2130
+ mod lifetime_extension {
2131
+ use crate :: marker:: PhantomData ;
2132
+ use crate :: ops:: { Deref , DerefMut } ;
2133
+
2134
+ /// Used in an `unreachable_code` branch to guide type inference.
2135
+ #[ doc( hidden) ]
2136
+ pub fn __phantomdata_set_typeof_pointee < T > ( _: PhantomData < & mut T > , _: T ) { }
2137
+
2138
+ /// Our `DerefMut` helper wrapper.
2139
+ #[ doc( hidden) ]
2140
+ #[ unstable( feature = "unsafe_pin_internals" , issue = "none" ) ]
2141
+ #[ allow( missing_debug_implementations) ]
2142
+ pub struct __Pinned < T > {
2143
+ pub value_expression_preserving_lifespan_extension_of_temporaries : T ,
2144
+ }
2145
+
2146
+ impl < T > Deref for __Pinned < T > {
2147
+ type Target = T ;
2148
+
2149
+ fn deref ( & self ) -> & T {
2150
+ unimplemented ! ( "never to be called" ) ;
2151
+ }
2152
+ }
2153
+
2154
+ impl < T > DerefMut for __Pinned < T > {
2155
+ #[ inline]
2156
+ fn deref_mut ( & mut self ) -> & mut T {
2157
+ & mut self . value_expression_preserving_lifespan_extension_of_temporaries
2158
+ }
2159
+ }
2018
2160
}
2161
+
2162
+ #[ unstable( feature = "unsafe_pin_internals" , issue = "none" ) ]
2163
+ pub use lifetime_extension:: { __Pinned, __phantomdata_set_typeof_pointee} ;
0 commit comments