Skip to content

Trouble unifying function types involving HRTB #84937

Closed
@Manishearth

Description

@Manishearth
use std::borrow::{Cow,  ToOwned};

pub trait Yokeable<'a> : 'static {
    type Transformed: 'a + Sized;
}

impl<'a, T: ToOwned + ?Sized> Yokeable<'a> for Cow<'static, T> {
    type Transformed = Cow<'a, T>;
}

pub fn attach<Y: 'static, F>(f: F)
where
    F: for<'de> FnOnce(&'de [u8]) -> <Y as Yokeable<'de>>::Transformed,
{
    unimplemented!()
}
fn deserialize<'d>(data: &'d [u8]) -> <Cow<'static, [u8]> as Yokeable<'d>>::Transformed {
    unimplemented!()
}

fn deserialize2<'d>(data: &'d [u8]) -> Cow<'d, [u8]> {
    unimplemented!()
}

fn main() {
    attach::<Cow<'static, [u8]>, _>(deserialize);
}

(playpen)

throws up the following error, both when using deserialize and deserialize2 in `attach

error[E0271]: type mismatch resolving `for<'de> <for<'d> fn(&'d [u8]) -> <Cow<'static, [u8]> as Yokeable<'d>>::Transformed {deserialize} as FnOnce<(&'de [u8],)>>::Output == <Cow<'static, [u8]> as Yokeable<'de>>::Transformed`
  --> src/main.rs:26:5
   |
11 | pub fn attach<Y: 'static, F>(f: F)
   |        ------ required by a bound in this
12 | where
13 |     F: for<'de> FnOnce(&'de [u8]) -> <Y as Yokeable<'de>>::Transformed,
   |                                      --------------------------------- required by this bound in `attach`
...
26 |     attach::<Cow<'static, [u8]>, _>(deserialize);
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found enum `Cow`
   |
   = note: expected associated type `<Cow<'static, [u8]> as Yokeable<'_>>::Transformed`
                         found enum `Cow<'_, [u8]>`
   = help: consider constraining the associated type `<Cow<'static, [u8]> as Yokeable<'_>>::Transformed` to `Cow<'_, _>` or calling a method that returns `<Cow<'static, [u8]> as Yokeable<'_>>::Transformed`

This is a reduced version of my full testcase here.

The types are indeed the same, in the case of deserialize() they've literally been written out to be exactly the same, yet the compiler seems to have trouble. If I write out an actual meaningful body for deserialize() the body compiles just fine -- rustc is able to unify it there, but not when comparing Fn types

Even more confusing, I get a similar error when I swap out deserialize with |data| { unimplemented!() }, which is mystifying since the closure passed does not have a known Output type and yet the error is talking about unifying Cow<'_, [u8]> with the associated type. I feel like there's a bug involved here somewhere.

cc @eddyb @tmandry

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-lifetimesArea: Lifetimes / regionsA-trait-systemArea: Trait systemE-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions