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

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

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in 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