Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trait bounds were not satisfied #69169

Open
ababo opened this issue Feb 14, 2020 · 6 comments
Open

Trait bounds were not satisfied #69169

ababo opened this issue Feb 14, 2020 · 6 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-lifetimes Area: Lifetimes / regions C-enhancement Category: An issue proposing an enhancement or a PR with one. E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@ababo
Copy link

ababo commented Feb 14, 2020

I'm not sure if this is a compiler bug, but since I didn't get any answers on StackOverflow I'd try to add an issue here.

I tried this code:

use futures_util::compat::Future01CompatExt;
use gluon::{
    new_vm,
    vm::api::{FunctionRef, Getable, Pushable, VmType},
    ThreadExt,
};

pub type Error = gluon::Error;

pub struct Script<'vm, 'value, In, Out>
where
    In: VmType + Pushable<'vm>,
    Out: VmType + Getable<'vm, 'value> + Send + Sync,
{
    vm: gluon::RootedThread,
}

impl<'vm, 'value, In, Out> Script<'vm, 'value, In, Out>
where
    In: VmType + Pushable<'vm>,
    Out: VmType + Getable<'vm, 'value> + Send + Sync,
{
    pub fn read(text: &str) -> Result<Script<In, Out>, Error> {
        let mut vm = new_vm();

        vm.run_io(true);

        vm.load_script("main", text).map(|()| Script { vm: vm })
    }

    pub async fn run(&mut self, input: &In) -> Result<Out, Error> {
        let func: FunctionRef<fn(In) -> Out> = self.vm.get_global("main")?;

        return func.call_async(input).compat().await;
    }
}

As you can see I explicitly bound In and Out with the needed traits, but still get "trait bounds were not satisfied" error.

rustc --version --verbose:

rustc 1.41.0
binary: rustc
commit-hash: unknown
commit-date: unknown
host: x86_64-alpine-linux-musl
release: 1.41.0
LLVM version: 9.0
@ababo ababo added the C-bug Category: This is a bug. label Feb 14, 2020
@jonas-schievink
Copy link
Contributor

This demands a different lifetime than what you provided: Out : gluon_vm::api::Getable<'x, 'value>

@ababo
Copy link
Author

ababo commented Feb 14, 2020

Yep, but that doesn't solve the issue. Updated.

@nagisa
Copy link
Member

nagisa commented Feb 15, 2020

This code is extremely hard to make sense and I think the confusion comes entirely from the fact that the lifetimes used in gluon and in this code have matching names – which is why the compiler notes appear to be wrong – while they actually aren't.

For instance even if you rewrite the code as such:

use futures_util::compat::Future01CompatExt;
use gluon::{
    vm::api::{FunctionRef, Getable, Pushable, VmType},
};

pub type Error = gluon::Error;

pub struct Script<'banana, 'peach, In, Out>
where
    In: VmType + Pushable<'banana>,
    Out: VmType + Getable<'banana, 'peach> + Send + Sync,
{
    vm: gluon::RootedThread,
}

impl<'banana, 'peach, In, Out> Script<'banana, 'peach, In, Out>
where
    In: VmType + Pushable<'banana>,
    Out: VmType + Getable<'banana, 'peach> + Send + Sync,
{
    pub async fn run(&mut self, input: &In) -> Result<Out, Error> {
        let func: FunctionRef<fn(In) -> Out> = self.vm.get_global("main")?;

        return func.call_async(input).compat().await;
    }
}

you will get exactly the same error as before:

error[E0599]: no method named `call_async` found for type `gluon::gluon_vm::api::Function<&gluon::Thread, fn(In) -> Out>` in the current scope
  --> src/lib.rs:27:21
   |
27 |         return func.call_async(input).compat().await;
   |                     ^^^^^^^^^^ method not found in `gluon::gluon_vm::api::Function<&gluon::Thread, fn(In) -> Out>`
   |
   = note: the method `call_async` exists but the following trait bounds were not satisfied:
           `In : gluon::gluon_vm::api::Pushable<'vm>`
           `Out : gluon::gluon_vm::api::Getable<'x, 'value>`

making it easier to see that this is at best a diagnostics bug.

@nagisa nagisa added the A-diagnostics Area: Messages for errors, warnings, and lints label Feb 15, 2020
@nagisa
Copy link
Member

nagisa commented Feb 15, 2020

(FWIW the code is extremely difficult to make sense of, I suspect that it was arrived to from the other end – that is, by looking at a compiler diagnostics and then adding lifetime bounds everywhere possible)

The following is something that at least compiles and makes some sense to at least me.

pub struct Script {
    vm: gluon::RootedThread,
}

impl Script
{
    pub async fn run<In, Out>(&mut self, input: In) -> Result<Out, Box<dyn std::error::Error>>
    where
        In: VmType + for<'banana> Pushable<'banana>,
        Out: VmType + for<'peach, 'mango> Getable<'peach, 'mango> + Send + Sync + 'static,
    {
        let mut func = self.vm.get_global::<FunctionRef<fn(In) -> Out>>("main")?;

        return Ok(func.call_async(input).compat().await?);
    }
}

@ababo
Copy link
Author

ababo commented Feb 15, 2020

I'm curious whom to blame in this patricular case:

  1. Myself, a guy with a lot of experiece developing in other languages (e.g. C/C++), who didn't have a chance to get intimately familiar with Rust before trying to compose something pretty simple with Gluon.
  2. Gluon, which is designed functionally overengineered by a guy with a Haskell background.
  3. The compiler for not emitting sane messages and demanding usage of higher-rank trait bounds which are so obscure that aren't even mentioned in its Book.

BTW, your fix doesn't reflect my original intentions. I would like to make the script parametrised.

@nagisa
Copy link
Member

nagisa commented Feb 15, 2020

I'm curious whom to blame in this patricular case:

Some fault definitely lies in the compiler for being confusing about the lifetime names it puts in the diagnostic hints. Hence the A-diagnostics label. Whether HRTBs would make sense in any particular scenario is not for the compiler to decide – it affects the public API after all and is something that you’d need to arrive to yourself.

@jonas-schievink jonas-schievink added A-lifetimes Area: Lifetimes / regions T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. C-enhancement Category: An issue proposing an enhancement or a PR with one. and removed C-bug Category: This is a bug. labels Feb 15, 2020
@estebank estebank added the E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example label May 16, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-lifetimes Area: Lifetimes / regions C-enhancement Category: An issue proposing an enhancement or a PR with one. E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants