Change:
I tried this code: It used to compile on 1.69, so I expected it to compile under 1.70, but it failed with the following error The same happens for structs that contain a reference and derive . () 69 70 : modify labels: +regression-from-stable-to-stable -regression-untriaged
searched nightlies: from nightly-2023-03-01 to nightly-2023-06-21 regressed nightly: nightly-2023-03-29 searched commit range: regressed commit: <details<summarybisected with <a href=''cargo-bisect-rustc</av0.6.5</summaryHost triple: aarch64-unknown-linux-gnu Reproduce with: </detailsThis probably regressed in .
I don't know if this predicate should have held in the first place I think code demonstrates that doesn't hold -- the lifetimes have to be equal as a consequence of the implementation for tuples
The previous behavior is unsound, demonstrated by this code which passed in 1.69 and fails in 1.70:
fwiw this could possible pass if the impl for tuples in std was instead of . But that won't fix the general cause of breakage which is that code was being accepted without trait bounds holding which is unsound, and now those bounds do have to hold which cannot be fixed for all breakages.
I think there are two actionable steps there: to fix this concrete breakage, and because it is strictly more powerful, we can try to change the impls in to as stated by this may worsen inference but feels generally worthwhile to me. does not mention that it fixes an unsoundness, we should add the example by as a test
(1.) is not feasible, I think. See the crater results for But yeah, we should add a test for the unsoundness I shared above.
WG-prioritization assigning priority (). label -I-prioritize +P-medium
Breaking code via breaking inference is, strictly speaking, a permitted breakage. Of course, breaking unsound code is, in a greater sense, also permitted breakage.
Is there a way to measure the impact of that crater run on the ecosystemt? Breakage in serde or chrono would be surely a more serious problem than a breakage in a toy application and with untrained eye I can't tell if the breakage is disastrous or just a little beyond acceptable. Improving the implementation for tuples strikes me as a "right thing to do" for the standard library. If we can't have it now, would it be possible to change it in a new edition? It would be sad if we were stuck forever with the current implementation when a strictly more powerful one exists.
The stdlib's implementations are largely unrelated to the edition mechanism: the editions mostly introduce syntactic changes, not library changes, with the one blurriness being with macros which interact with syntax. What really needs to improve is the algorithm for deducing types, then it would be easier for the stdlib to carry more powerful implementations without fear of breaking inference.

Discussion:
<ins> // This test checks that we correctly reject the following unsound code. trait Lengthen<T> { fn lengthen(self) -> T; } impl<'a> Lengthen<&'a str> for &'a str { fn lengthen(self) -> &'a str { self } } trait Gat { type Gat<'a>: for<'b> Lengthen<Self::Gat<'b>>; fn lengthen(s: Self::Gat<'_>) -> Self::Gat<'static> { s.lengthen() } } impl Gat for () { type Gat<'a> = &'a str; //~ ERROR: implementation of `Lengthen` is not general enough } fn main() { let s = "hello, garbage".to_string(); let borrow: &'static str = <() as Gat>::lengthen(&s); drop(s); println!("{borrow}"); } </ins>

<ins> error: implementation of `Lengthen` is not general enough --> $DIR/gat-bounds-not-checked-with-right-substitutions.rs:20:20 | LL |     type Gat<'a> = &'a str; |                    ^^^^^^^ implementation of `Lengthen` is not general enough | = note: `Lengthen<&'0 str>` would have to be implemented for the type `&'a str`, for any lifetime `'0`... = note: ...but `Lengthen<&'1 str>` is actually implemented for the type `&'1 str`, for some specific lifetime `'1` error: aborting due to previous error </ins>