Skip to content

Associated type constraint fails, even if it implements requested trait #76407

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

Closed
Mr-Andersen opened this issue Sep 6, 2020 · 7 comments · Fixed by #86993
Closed

Associated type constraint fails, even if it implements requested trait #76407

Mr-Andersen opened this issue Sep 6, 2020 · 7 comments · Fixed by #86993
Labels
A-GATs Area: Generic associated types (GATs) A-lazy-normalization Area: Lazy normalization (tracking issue: #60471) C-bug Category: This is a bug. F-generic_associated_types `#![feature(generic_associated_types)]` a.k.a. GATs requires-nightly This issue requires a nightly compiler in some way.

Comments

@Mr-Andersen
Copy link

Associated type constraint fails, even if it implements requested trait. In the example below, requested trait is Marker, u32 implements it, <MyStruct as MyTrait>::Item<'a> == u32, but <MyStruct as MyTrait>::Item<'a>: Marker does not pass. (Everything is ok with <'a> removed)

The code:

#![allow(incomplete_features)]
#![feature(generic_associated_types)]

trait Marker {}

impl Marker for u32 {}

trait MyTrait {
    type Item<'a>;
}

struct MyStruct;

impl MyTrait for MyStruct {
    type Item<'a> = u32;
}

fn ty_check<T>()
where
    T: MyTrait,
    for<'a> T::Item<'a>: Marker
{}

fn main() {
    ty_check::<MyStruct>();
}

Meta

rustc --version --verbose:

rustc 1.48.0-nightly (cdc8f0606 2020-09-05)
binary: rustc
commit-hash: cdc8f0606d0f3c4f3866643382c8a5776d1bdaed
commit-date: 2020-09-05
host: x86_64-unknown-linux-gnu
release: 1.48.0-nightly
LLVM version: 11.0
@Mr-Andersen Mr-Andersen added the C-bug Category: This is a bug. label Sep 6, 2020
@Mr-Andersen Mr-Andersen changed the title Associated type constraint fails, even if Associated type constraint fails, even if it implements requested trait Sep 6, 2020
@jonas-schievink jonas-schievink added F-generic_associated_types `#![feature(generic_associated_types)]` a.k.a. GATs requires-nightly This issue requires a nightly compiler in some way. labels Sep 6, 2020
@Mr-Andersen
Copy link
Author

Also, if type Item<'a>: Marker; in MyTrait, the code compiles.

@nikomatsakis
Copy link
Contributor

This variant also fails to compile, but doesn't use GATs:

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=1ea06f6d50ae8a612feb5a22279e2889

My guess is that this is the same bug. We are missing a normalization somewhere.

@jackh726
Copy link
Member

jackh726 commented Feb 6, 2021

Projections aren't getting normalized because:

ty::Projection(data) if !data.has_escaping_bound_vars() => {

@matthewjasper matthewjasper added the A-lazy-normalization Area: Lazy normalization (tracking issue: #60471) label Feb 6, 2021
@NathanIceSea
Copy link

I could confirm with TryFrom trait associated type Error's Debug constraint, used as generic return type

@cynecx
Copy link
Contributor

cynecx commented May 12, 2021

Another test-case copied from #79768 (@jackh726 mentioned that this might be related to this one):

#![feature(generic_associated_types)]

trait Monad {
    type Unplug;
    type Plug<B>: Monad;

    fn bind<B, F>(self, f: F) -> Self::Plug<B>
    where
        F: Fn(Self::Unplug) -> Self::Plug<B>;
}

impl<A> Monad for Option<A> {
    type Unplug = A;
    type Plug<B> = Option<B>;
    
    fn bind<B, F>(self, f: F) -> Option<B>
    where
        F: Fn(A) -> Option<B>,
    {
        self.and_then(f)
    }
}

fn stringify<T, M1>(m: M1) -> <M1 as Monad>::Plug<String>
where
    T: core::fmt::Display,
    M1: Monad<Unplug = T>,
{
    m.bind(|x| Some(format!("{}", x)))
}

@SkiFire13
Copy link
Contributor

SkiFire13 commented May 20, 2021

@cynecx I don't think your example should compile. M1 is not guaranteed to be Option<T>, there could be other types that impement Monad<Unplug=T> whose Plug<B> associated type is not Option<B>. For example if I add another impl for Result<A, ()> like the following then stringify will not be valid anymore when M1 = Result<T, ()>:

#![feature(generic_associated_types)]

trait Monad {
    type Unplug;
    type Plug<B>: Monad;

    fn bind<B, F>(self, f: F) -> Self::Plug<B>
    where
        F: Fn(Self::Unplug) -> Self::Plug<B>;
}

impl<A> Monad for Option<A> {
    type Unplug = A;
    type Plug<B> = Option<B>;
    
    fn bind<B, F>(self, f: F) -> Option<B>
    where
        F: Fn(A) -> Option<B>,
    {
        self.and_then(f)
    }
}

impl<A> Monad for Result<A, ()> {
    type Unplug = A;
    type Plug<B> = Result<B, ()>;
    
    fn bind<B, F>(self, f: F) -> Result<B, ()>
    where
        F: Fn(A) -> Result<B, ()>
    {
        self.and_then(f)
    }
}

fn stringify<T, M1>(m: M1) -> <M1 as Monad>::Plug<String>
where
    T: core::fmt::Display,
    M1: Monad<Unplug = T>,
{
    m.bind(|x| Some(format!("{}", x)))
}

fn main() {
    let a: Result<i32, ()> = Ok(0);
    stringify(a); // In this case <M1 as Monad>::Plug<String> = Result<String, ()>`, not `Option<String>`!
}

Edit: the following compiles, this may be what you want:

#![feature(generic_associated_types)]

trait Monad {
    type Unplug;
    type Plug<B>: Monad<Unplug = B>;

    fn plug(t: Self::Unplug) -> Self;

    fn bind<B, F>(self, f: F) -> Self::Plug<B>
    where
        F: Fn(Self::Unplug) -> Self::Plug<B>;
}

impl<A> Monad for Option<A> {
    type Unplug = A;
    type Plug<B> = Option<B>;
    
    fn plug(t: Self::Unplug) -> Self {
        Some(t)
    }
    
    fn bind<B, F>(self, f: F) -> Option<B>
    where
        F: Fn(A) -> Option<B>,
    {
        self.and_then(f)
    }
}

fn stringify<T, M1>(m: M1) -> <M1 as Monad>::Plug<String>
where
    T: core::fmt::Display,
    M1: Monad<Unplug = T>,
{
    m.bind(|x| M1::Plug::plug(format!("{}", x)))
}

@cynecx
Copy link
Contributor

cynecx commented May 20, 2021

@SkiFire13 Oh wow. (...I feel stupid). Thanks for pointing that out :D

@bors bors closed this as completed in 27e4205 Jul 16, 2021
@fmease fmease added the A-GATs Area: Generic associated types (GATs) label Nov 2, 2024
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-GATs Area: Generic associated types (GATs) A-lazy-normalization Area: Lazy normalization (tracking issue: #60471) C-bug Category: This is a bug. F-generic_associated_types `#![feature(generic_associated_types)]` a.k.a. GATs requires-nightly This issue requires a nightly compiler in some way.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants