Borrow checker fails to pick up existing region bounds in the environment when aliases are given to assoicated types in trait bounds.
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
It occurs to me that adding named type terms to associated type of trait bounds can lead to borrow check failure, while the same code without "naming" the associated type passes the borrow check.
I tried this code:
pub trait Trait1 {
type Output1;
fn call<'z>(&'z self) -> &'z Self::Output1;
}
pub trait Trait2<T> {
type Output2;
fn call2<'x>(_: &'x T) -> &'x Self::Output2;
}
impl<A, B, T: Trait1<Output1 = A>> Trait2<T> for B // Mind this `A` here
where
B: Trait2<T::Output1>,
{
type Output2 = <B as Trait2<T::Output1>>::Output2;
fn call2<'y>(source: &'y T) -> &'y Self::Output2 {
let t = source.call();
B::call2(t)
}
}
I expected to see this happen:
It should compile just like the following rewrite, without naming the Output1 to A.
pub trait Trait1 {
type Output1;
fn call<'z>(&'z self) -> &'z Self::Output1;
}
pub trait Trait2<T> {
type Output2;
fn call2<'x>(_: &'x T) -> &'x Self::Output2;
}
impl<B, T: Trait1> Trait2<T> for B
where
B: Trait2<T::Output1>,
{
type Output2 = <B as Trait2<T::Output1>>::Output2;
fn call2<'y>(source: &'y T) -> &'y Self::Output2 {
let t = source.call();
B::call2(t)
}
}
Instead, this happened:
error[E0309]: the parameter type `A` may not live long enough
--> lifetime.rs:17:17
|
16 | fn call2<'y>(source: &'y T) -> &'y Self::Output2 {
| -- the parameter type `A` must be valid for the lifetime `'y` as defined here...
17 | let t = source.call();
| ^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound
|
16 | fn call2<'y>(source: &'y T) -> &'y Self::Output2 where A: 'y {
| +++++++++++
error[E0309]: the parameter type `A` may not live long enough
--> lifetime.rs:18:9
|
16 | fn call2<'y>(source: &'y T) -> &'y Self::Output2 {
| -- the parameter type `A` must be valid for the lifetime `'y` as defined here...
17 | let t = source.call();
18 | B::call2(t)
| ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound
|
16 | fn call2<'y>(source: &'y T) -> &'y Self::Output2 where A: 'y {
| +++++++++++
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0309`.
Mind that due to the trait definition, it is not possible to apply the suggestion that is emitted by rustc.
Meta
This is found on the latest master, as of writing, and stable.
rustc --version --verbose:
rustc 1.78.0-nightly (256b6fb19 2024-02-06)
binary: rustc
commit-hash: 256b6fb19a2c018eaad4806d2369d1f6a71fc6ec
commit-date: 2024-02-06
host: x86_64-unknown-linux-gnu
release: 1.78.0-nightly
LLVM version: 17.0.6
Backtrace
Not an ICE, so not applicable.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by compiling the first Rust reproducer with the reported stable or nightly compiler and compare it with the rewrite that omits the associated-type alias. Trace the borrow-checker handling of the named Output1 = A trait bound; done means the original example compiles without adding the impossible A: 'y bound.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100