Open Kimundi opened 2 years ago
Okay, so here's what's happening:
So, we look up the function <<Self as FunctorExt<T>>::Base as Functor>::fmap
, and get something that's roughly fn(<<Self as FunctorExt<T>>::Base as Functor>::With<?0>) -> <<Self as FunctorExt<T>>::Base as Functor>::With<?1>
. Then, we try to normalize <<Self as FunctorExt<T>>::Base as Functor>::With<?1>
and we find the predicate (ProjectionCandidate) <<Self as FunctorExt<T>>::Base as Functor>::With<T> = Self
, so we set ?1 = T
, normalize and get Self
. So, after complete normalization, we get fn(Self) -> Self
. Well, that second return type shouldn't have normalized, because T != U
, and we never actually compared that.
Now, two potential ways to fix this: 1) Maybe just delay normalizing the function signature so we don't end up trying to set ?1 = T
and normalizing so early. This is potentially tricky, since we might need to normalize for other type checking. 2) Use T
and U
instead of inference vars. But that might mess with caching.
Will look into this more soon.
I have a "working" branch here: https://github.com/jackh726/rust/tree/issue-91762
But it's absolutely awful and probably not a "correct" solution.
no_std
repro, for reference:
#![feature(generic_associated_types)]
#![feature(lang_items)]
#![feature(no_core)]
#![no_core]
#![crate_type = "rlib"]
#[lang = "sized"]
pub trait Sized {}
#[lang = "copy"]
pub trait Copy {}
pub trait Functor {
type With<T>;
fn fmap<T, U>(this: Self::With<T>) -> Self::With<U>;
}
pub trait FunctorExt<T>: Sized {
type Base: Functor<With<T> = Self>;
fn fmap<U>(self) {
let arg: <Self::Base as Functor>::With<T>;
let ret: <Self::Base as Functor>::With<U>;
arg = self;
ret = <Self::Base as Functor>::fmap(arg);
}
}
GATs issue triage: not blocking. The example can compile by changing the ret =
line to ret = <Self::Base as Functor>::fmap::<T, U>(arg)
. We've updated the code so that we no longer arbitrarily constrain inference vars in GAT substs when projecting an associated type, which would have been a backwards-compatibility hazard. We would like the current test to compile eventually, but doing so is backwards-compatible and not doing so right now isn't a huge ergonomic hurdle given the fix above.
In this code:
I would expect the code in
FunctorExt
to compile, as I'm constrainingSelf::Base::With<T> = Self
, whileSelf::Base::With<U>
should just be whateverWith<T>
is without any extra constraints.But I'm getting this compiler error:
It seems to me as if the
Base: Functor<With<T> = Self>;
constraint causes rustc to think that anyWith<X>
should be the same type asSelf
, rather than just the oneWith<T>
for the specificT
in scope.Meta
rustc --version --verbose
: