@@ -2284,23 +2284,45 @@ declare_lint! {
22842284 ///
22852285 /// ### Explanation
22862286 ///
2287- /// If a `struct` contains a reference, such as `&'a T`, the compiler
2288- /// requires that `T` outlives the lifetime `'a`. This historically
2289- /// required writing an explicit lifetime bound to indicate this
2290- /// requirement. However, this can be overly explicit, causing clutter and
2291- /// unnecessary complexity. The language was changed to automatically
2292- /// infer the bound if it is not specified. Specifically, if the struct
2293- /// contains a reference, directly or indirectly, to `T` with lifetime
2294- /// `'x`, then it will infer that `T: 'x` is a requirement.
2295- ///
2296- /// This lint is "allow" by default because it can be noisy for existing
2297- /// code that already had these requirements. This is a stylistic choice,
2298- /// as it is still valid to explicitly state the bound. It also has some
2299- /// false positives that can cause confusion.
2287+ /// If a struct, enum or union contains a reference, such as `&'a T`,
2288+ /// the compiler requires that `T` outlives the lifetime `'a`.
2289+ /// This historically required writing an explicit lifetime bound to indicate this requirement.
2290+ /// However, this can be overly explicit, causing clutter and unnecessary complexity.
2291+ /// The language was changed to automatically infer some classes of lifetime bounds
2292+ /// if they are not specified.
2293+ /// Specifically, if a struct, enum or union contains a reference, directly or indirectly,
2294+ /// to `T` with lifetime `'x` and `'x` refers to a lifetime parameter,
2295+ /// then it will infer that `T: 'x` is a requirement.
23002296 ///
23012297 /// See [RFC 2093] for more details.
23022298 ///
2299+ /// > [!WARNING]
2300+ /// > Implicit lifetime bounds are not semantically equivalent to explicit ones since the latter
2301+ /// > may affect the implicit lifetime bound of trait object types that are passed as arguments
2302+ /// > to the overarching struct, enum or union.
2303+ /// > Rephrased, they participate in [trait object lifetime defaulting][TOLD].
2304+ /// >
2305+ /// > Consider the following piece of code where removing bound `T: 'a` would lead to a lifetime
2306+ /// > error in function `scope`:
2307+ /// >
2308+ /// > ```rust,no_run
2309+ /// > struct Ref<'a, T: ?Sized + 'a>(&'a T);
2310+ /// >
2311+ /// > fn scope() {
2312+ /// > let buf = String::new();
2313+ /// > let str = buf.as_str();
2314+ /// > render(Ref(&str));
2315+ /// > }
2316+ /// >
2317+ /// > fn render(_: Ref<dyn std::fmt::Display>) {}
2318+ /// > ```
2319+ /// >
2320+ /// > Consequently, removing explicit outlives-bounds on type parameters of publicly reachable types
2321+ /// > constitutes a **breaking change** if the lifetime refers to a lifetime parameter and
2322+ /// > the type parameter is not bounded by `Sized` (thereby admitting trait object types).
2323+ ///
23032324 /// [RFC 2093]: https://github.com/rust-lang/rfcs/blob/master/text/2093-infer-outlives.md
2325+ /// [TOLD]: https://doc.rust-lang.org/reference/lifetime-elision.html#default-trait-object-lifetimes
23042326 pub EXPLICIT_OUTLIVES_REQUIREMENTS ,
23052327 Allow ,
23062328 "outlives requirements can be inferred"
0 commit comments