-
Notifications
You must be signed in to change notification settings - Fork 13.3k
HRTB bounds not resolving correctly (take 3, lifetimes on the RHS) #90950
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Comments
😔 always another HRTB issue Based on |
@jackh726 yeah, sorry 😅 But that diagnosis makes sense |
I think I just ran into this issue: trait SomeOtherTrait<'a> {
fn create(string: &'a mut str) -> Self;
}
trait SomeTrait<'a> {
type Associated;
fn do_stuff(&self, other: &mut Self::Associated);
}
fn something_else<T>(v: T)
where
for<'b> T: SomeTrait<'b>,
for<'b> <T as SomeTrait<'b>>::Associated: SomeOtherTrait<'b>,
{
let mut message = "Hello".to_string();
{
let evil_borrow = <T::Associated as SomeOtherTrait<'_>>::create(message.as_mut_str());
}
}
struct FooAssociated<'a> {
blah: &'a str,
}
impl<'a> SomeOtherTrait<'a> for FooAssociated<'a> {
fn create(string: &'a mut str) -> Self {
Self { blah: string }
}
}
struct Foo {}
impl<'a> SomeTrait<'a> for Foo {
type Associated = FooAssociated<'a>;
fn do_stuff(&self, other: &mut Self::Associated) {
// ...
}
}
fn foo(x: Foo) {
something_else(x);
} For those who stumble upon this, I found this workaround that may or may not be applicable to your situation: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=f4b1074af9207306222d37d2ed5a317f (create another trait with the desired associated type bounds and a blanket impl) trait SomeTraitWithOtherAssociated<'a> {
type Associated: SomeOtherTrait<'a>;
}
impl<'a, T: SomeTrait<'a>> SomeTraitWithOtherAssociated<'a> for T
where
for<'b> <T as SomeTrait<'b>>::Associated: SomeOtherTrait<'b>,
{
type Associated = <T as SomeTrait<'a>>::Associated;
}
fn something_else<T>(v: T)
where
for<'b> T: SomeTraitWithOtherAssociated<'b>,
{
// ... |
I'd like to mention another use-case where this issue (as I understand it) comes up. Sometimes, people want to write a HRTB for fn choose_randomly<It>(
game: &mut GameState,
generator: impl FnOnce(&GameState) -> It,
) -> Option<It::Item>
where
It: Iterator, But this doesn't work because fn choose_randomly<G, Item>(
game: &mut GameState,
generator: G,
) -> Option<Item>
where
for<'any> G: GeneratesIterator<'any, Item=Item>, Conceptually, you shouldn't need this, because the outputs of the fn choose_randomly<G, Item>(
game: &mut GameState,
generator: G,
) -> Option<Item>
where
for<'any> G: FnOnce<(&'any GameState,)>,
for<'any> <G as FnOnce<(&'any GameState,)>>::Output: Iterator<Item = Item> + 'any, ➡️
You can't name closures or function items, so the workaround of being explicit about the type is not ideal. I didn't keep the playground handy, but with the stable workaround, if you don't thread enough associated types like |
Current output
|
…imulacrum Add a few known-bug tests The labels of these tests should be changed from `S-bug-has-mcve` to `S-bug-has-test` once this is merged. cc: rust-lang#101518 rust-lang#99492 rust-lang#90950 rust-lang#89196 rust-lang#104034 rust-lang#101350 rust-lang#103705 rust-lang#103899 I couldn't reproduce the failures in rust-lang#101962 and rust-lang#100772 (so either these have started passing, or I didn't repro properly), so leaving those out for now. rust-lang#102065 was a bit more complicated, since it uses `rustc_private` and I didn't want to mess with that.
I’ve only tested the first two examples, but this hasn’t been mentioned here yet – the code examples compile successfully if the type argument is specified explicitly, e.g. calling |
That code fails to compile: struct Opaque;
trait FromRef<'r>: 'r {
fn from_ref(_: &'r Opaque) -> Self;
}
struct Bar<'r>(&'r Opaque);
impl<'r> FromRef<'r> for Bar<'r> {
fn from_ref(op: &'r Opaque) -> Self {
Bar(op)
}
}
trait Foo<I, O> {
fn call_foo(&self, op: &Opaque);
}
impl<I: for<'r> FromRef<'r>, O, H: Fn(I) -> O> Foo<I, O> for H {
fn call_foo(&self, op: &Opaque) {
let i = I::from_ref(op);
let _: O = self(i);
}
}
struct FooImpl;
impl<I: for<'r> FromRef<'r>> Foo<I, ()> for FooImpl {
fn call_foo(&self, op: &Opaque) {
let _ = I::from_ref(op);
}
}
fn asserted<'r>(_: Bar<'r>) {}
fn main() {
let op = Opaque;
// fails:
asserted.call_foo(&op);
// also fails:
FooImpl.call_foo(&op);
} While working on another code from picoserve I got such note, which guided me here. If this is not the right place, please guide me to elsewhere |
This is a new version of #85636 and #89196 . When reporting it I first hit an ICE which got fixed in #90638.
The basic idea is that bounds of the form
for<'a> <Type as Trait<'a>>::AssocType: OtherTrait<'a>
don't work. #85636, which has since been fixed, is about this same issue without a lifetime on the right side of the bound. This will likely also be a problem for GATs.The commented out code is not necessary for it to work, but it gives an idea of why such a bound might be necessary.
(playpen)
The error shown is:
which is incorrect, that bound is satisfied here.
I'm currently working on rustc master (d914f17) so that I can have the fix for #90638, though that fix is not necessary for the commented-out version of my code to work. This should be available on nightly soon.
cc @jackh726 @eddyb
The text was updated successfully, but these errors were encountered: