Repository navigation
TAIT regression: requires new lifetime bounds #95922
Copy link
Copy link
Closed
Labels
C-bugCategory: This is a bug.Category: This is a bug.F-type_alias_impl_trait`#[feature(type_alias_impl_trait)]``#[feature(type_alias_impl_trait)]`T-typesRelevant to the types team, which will review and decide on the PR/issue.Relevant to the types team, which will review and decide on the PR/issue.requires-nightlyThis issue requires a nightly compiler in some way. When possible, use a F-* label instead.This issue requires a nightly compiler in some way. When possible, use a F-* label instead.
Description
Edit: The original example was indeed unsound so it's thankfully rejected now. See this comment for a sound example that gets rejected.
Original unsound code
#![feature(type_alias_impl_trait)]
use core::future::Future;
trait Service<'a, Req> {
type Future: Future;
fn call(req: &'a Req) -> Self::Future;
}
impl<'a, Req> Service<'a, Req> for u8 {
type Future = impl Future;
fn call(req: &'a Req) -> Self::Future {
async move { let x = req; }
}
}This code used to compile fine prior to #95519. It now requires an explicit lifetime bound Req: 'a to the impl.
Unfortunately, adding a lifetime bound may not be an option when used with HRTBS due to limitations like #95921. This caused a major breakage on my part.
Meta
regressed in the nightly version 1.62.0-nightly (f4a7ce997 2022-04-08)
Error Output
Compiling rust-ci v0.1.0 (/home/runner/work/rust-ci/rust-ci)
error[E0309]: the parameter type `Req` may not live long enough
Error: --> src/lib.rs:10:19
|
10 | type Future = impl Future;
| ^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `Req: 'a`...
= note: ...so that the reference type `&'a Req` does not outlive the data it points at
For more information about this error, try `rustc --explain E0309`.
error: could not compile `rust-ci` due to previous error
Reacted by Mingwei Samuel
Metadata
Metadata
Assignees
Labels
C-bugCategory: This is a bug.Category: This is a bug.F-type_alias_impl_trait`#[feature(type_alias_impl_trait)]``#[feature(type_alias_impl_trait)]`T-typesRelevant to the types team, which will review and decide on the PR/issue.Relevant to the types team, which will review and decide on the PR/issue.requires-nightlyThis issue requires a nightly compiler in some way. When possible, use a F-* label instead.This issue requires a nightly compiler in some way. When possible, use a F-* label instead.
Type
Projects
- StatusShow more project fieldsDone
Activity
[-]TAIT regression: requires unnecessary explicit lifetime bound[/-][+]TAIT regression: requires new lifetime bounds[/+]aliemjay commentedon Apr 11, 2022
I thought this breakage is an unnecessary side effect to the PR, but this maybe the very unsound case that the PR tries to fix 😅 .
I'd appreciate a comment from @oli-obk @compiler-errors.
If it is unsound, wouldn't that make the following unsound as well?
oli-obk commentedon Apr 11, 2022
The problem is a bit roundabout.
Basically there is an implicit
Req: 'aon your method, sois in fact
(which is implied from
&'a Req).Now, TAIT desugars to putting a
&'a Reqinto the associatedtype Future, but unlike the method, this type does not have this bound. So you get an error telling you to add the bound to the trait impl.Ideally this would just be a
wherebound on the associated type. With GATs you can move the lifetime to the associated items, removing them from the trait, but I'm not sure if the where bound situation has been resolved already, I guess try addingwhere Req: 'ato the assoc type in your trait definition and the impl as well.oli-obk commentedon Apr 11, 2022
Nope, that case is easier, because the implicit
Req: 'a(implied from&'a Req) exists for the desugared type alias, too.aliemjay commentedon Apr 11, 2022
Thanks. So to conclude, this use case is indeed unsound and I'm happy it's now rejected.
One problem though I faced while redesigning the trait, TAIT now seems at a disadvantage to writing the full type:
Given the following example:
This still fails and requires the explicit bound
Req: 'adespite that, without TAIT, It is accepted and, I believe, is correct since the bound is implied by the trait parameter:This is really a deal-breaker for using TAIT because of #95921
Do you think this is an easy problem and we can expect a fix in the near future?
oli-obk commentedon Apr 11, 2022
Yea, so since your service trait now has
&'a Reqand not'a, Reqas parameters, this should indeed pass, as that should implyReq: 'a. (This is also the sound case I noticed in the PR that now needed more bounds).I'll fix this, but I'm going on vacation end of the week, so you may be in for a bit of a wait
oli-obk commentedon Apr 11, 2022
While digging into this I noticed that
-Zchalkwill immediately fix this, because it does exactly what I wanted to do. But... just enabling this unconditionally (and not just in chalk), causes libcore to stop compiling 😱Pretty sure I know why, too. This is gonna be a rabbit hole
oli-obk commentedon Apr 11, 2022
Side note:
may be more what you are looking for, but without knowing more about your use case, I can't be sure. (This issue requires solving regardless, but using a different scheme may unblock you)
aliemjay commentedon Apr 12, 2022
Unfortuanltely, I hit another blocker when using GATs as recommended:
This requires the bound
S: 's, but when added to the associated type rustc complains:So again adding the bound to the impl seems to be the only option.
Rollup merge of rust-lang#106038 - aliemjay:opaque-implied, r=lcnr
Rollup merge of rust-lang#106038 - aliemjay:opaque-implied, r=lcnr