Description
Here is an example which uses a RPIT on a borrowed type in three different ways:
use std::io::Write;
struct A(Vec<u8>);
struct B<'a> {
one: &'a mut A,
two: &'a mut Vec<u8>,
three: Vec<u8>,
}
impl<'a> B<'a> {
fn one(&mut self) -> &mut impl Write { &mut self.one.0 }
fn two(&mut self) -> &mut impl Write { &mut self.two } // fail
fn three(&mut self) -> &mut impl Write { &mut self.three }
}
struct C<'a>(B<'a>);
impl<'a> C<'a> {
fn one(&mut self) -> &mut impl Write { self.0.one() } // fail on beta
fn two(&mut self) -> &mut impl Write { self.0.two() } // fail on beta
fn three(&mut self) -> &mut impl Write { self.0.three() } // fail on beta
}
IMO this is perfectly reasonable code and there should be no errors (EDIT: see below). On stable (rustc 1.66.0 (69f9c33d7 2022-12-12)
) we have the following:
error[E0700]: hidden type for `impl std::io::Write` captures lifetime that does not appear in bounds
--> src/main.rs:13:42
|
11 | impl<'a> B<'a> {
| -- hidden type `&'a mut Vec<u8>` captures the lifetime `'a` as defined here
12 | fn one(&mut self) -> &mut impl Write { &mut self.one.0 }
13 | fn two(&mut self) -> &mut impl Write { &mut self.two } // fail
| ^^^^^^^^^^^^^
And on beta (rustc 1.67.0-beta.2 (352eb59a4 2022-12-13)
) and nightly (rustc 1.68.0-nightly (b70baa4f9 2022-12-14)
) we get some additional errors:
error[E0700]: hidden type for `impl std::io::Write` captures lifetime that does not appear in bounds
--> src/main.rs:13:42
|
11 | impl<'a> B<'a> {
| -- hidden type `&'a mut Vec<u8>` captures the lifetime `'a` as defined here
12 | fn one(&mut self) -> &mut impl Write { &mut self.one.0 }
13 | fn two(&mut self) -> &mut impl Write { &mut self.two } // fail
| ^^^^^^^^^^^^^
error: non-defining opaque type use in defining scope
--> src/main.rs:20:42
|
20 | fn one(&mut self) -> &mut impl Write { self.0.one() } // fail on beta
| ^^^^^^^^^^^^ lifetime `'a` is part of concrete type but not used in parameter list of the `impl Trait` type alias
error: non-defining opaque type use in defining scope
--> src/main.rs:21:42
|
21 | fn two(&mut self) -> &mut impl Write { self.0.two() } // fail on beta
| ^^^^^^^^^^^^ lifetime `'a` is part of concrete type but not used in parameter list of the `impl Trait` type alias
error: non-defining opaque type use in defining scope
--> src/main.rs:22:44
|
22 | fn three(&mut self) -> &mut impl Write { self.0.three() } // fail on beta
| ^^^^^^^^^^^^^^ lifetime `'a` is part of concrete type but not used in parameter list of the `impl Trait` type alias
EDIT: On second thought, I guess the first error (on stable) is reasonable, since we are actually returning a &mut &'a mut Vec<u8>
in that case. If you either use &mut *self.two
in the body or &mut (impl Write + 'a)
in the return type then the error goes away. But the second error is still a regression.
Version it worked on
It most recently worked on: rustc 1.66.0 (69f9c33 2022-12-12)
Version with regression
rustc --version --verbose
:
rustc 1.67.0-beta.2 (352eb59a4 2022-12-13)
binary: rustc
commit-hash: 352eb59a4c33abf739914422f2ad975925750146
commit-date: 2022-12-13
host: x86_64-unknown-linux-gnu
release: 1.67.0-beta.2
LLVM version: 15.0.6
@rustbot modify labels: +regression-from-stable-to-beta -regression-untriaged