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

GATs in Generics not working properly (not Generic) #117296

Closed
Aras14HD opened this issue Oct 27, 2023 · 3 comments
Closed

GATs in Generics not working properly (not Generic) #117296

Aras14HD opened this issue Oct 27, 2023 · 3 comments

Comments

@Aras14HD
Copy link

When used in generics (T: Trait<A = B>) GATs are not properly recognized, no scope for U is generated. All workarounds are hacky and limiting.

I tried this code:

trait Run<W> {
    type Wrapper<T>;
    fn run<T, F: FnOnce(W) -> Self::Wrapper<T>>(self, f: F) -> Self::Wrapper<T>;
    fn run_lazy<T, F: FnOnce(W) -> Self::Wrapper<T> + 'static>(
        self,
        f: F,
    ) -> Box<dyn FnOnce() -> Self::Wrapper<T>>
    where
        Self: Sized + 'static,
    {
        Box::new(|| self.run(f))
    }
}

trait RunTwo<W, V> {
    type Wrapper<T>;
    fn run<T, F: FnOnce(W, V) -> Self::Wrapper<T>>(self, f: F) -> Self::Wrapper<T>;
}

// Where it doesn't work properly
impl<A, B, X: Run<A>, Y: Run<B, Wrapper<T> = X::Wrapper<T>>> RunTwo<A, B> for (X, Y) {
    type Wrapper<T> = X::Wrapper<T>;
    fn run<T, F: FnOnce(A, B) -> Self::Wrapper<T>>(self, f: F) -> Self::Wrapper<T> {
        let (x, y) = self;
        x.run(|a| y.run(|b| f(a, b)))
    }
}

I expected to see this happen: The code should have compiled, as the output of y.run(...) which is of type Self::Wrapper<T> which is the same as Y::Wrapper<T> so also the same as X::Wrapper<T>.

Instead, this happened: While the compiler correctly recognizes that Self::Wrapper<T> == Y::Wrapper<T> it complains about the GAT assignment at Y: Run<B, Wrapper<T> = X::Wrapper<T>>, that T is not in scope. While I am able to circumvent this issue, the solution is hacky and likely not usable everywhere.

Meta

rustc --version --verbose:

rustc 1.71.1 (eb26296b5 2023-08-03)
binary: rustc
commit-hash: eb26296b556cef10fb713a38f3d16b9886080f26
commit-date: 2023-08-03
host: x86_64-unknown-linux-gnu
release: 1.71.1
LLVM version: 16.0.5
Backtrace

   Compiling monads v0.1.0 (/home/jorim/Documents/develop/Rust/monads)
error[E0412]: cannot find type `T` in this scope
  --> src/main.rs:40:41
   |
40 | impl<A, B, X: Run<A>, Y: Run<B, Wrapper<T> = X::Wrapper<T>>> RunTwo<A, B> for (X, Y) {
   |      -                                  ^ help: a type parameter with a similar name exists: `A`
   |      |
   |      similarly named type parameter `A` defined here

error[E0412]: cannot find type `T` in this scope
  --> src/main.rs:40:57
   |
40 | impl<A, B, X: Run<A>, Y: Run<B, Wrapper<T> = X::Wrapper<T>>> RunTwo<A, B> for (X, Y) {
   |      - similarly named type parameter `A` defined here  ^ help: a type parameter with a similar name exists: `A`

For more information about this error, try `rustc --explain E0412`.
error: could not compile `monads` (bin "monads") due to 2 previous errors

@Aras14HD Aras14HD added the C-bug Category: This is a bug. label Oct 27, 2023
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Oct 27, 2023
@Aras14HD
Copy link
Author

Repo where I encountered the issue: https://github.com/Aras14HD/monads/

@fmease
Copy link
Member

fmease commented Oct 27, 2023

This works as intended. The <A> in T: C<P<A> = U> is a list of generic arguments not generic parameters. Therefore, it doesn't define an A but it looks for a type named A. The bound reads type T implements trait C such that the generic associated type P equals U if we provide it with the argument A.

You are looking for Y: for<T> Run<B, Wrapper<T> = X::Wrapper<T>> (for all types T) which is not fully supported yet.

@saethlin saethlin removed C-bug Category: This is a bug. needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Oct 28, 2023
@fmease
Copy link
Member

fmease commented Oct 28, 2023

While it's unfortunate that you currently can't express what you have in mind, the specific code you submitted works as intended. The incomplete feature non_lifetime_binders (#108185) will at some point properly support type binders like for<T> which would solve your problem.

Closing as works-as-intended.

@fmease fmease closed this as not planned Won't fix, can't repro, duplicate, stale Oct 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants