Nested associated type projection is overly conservative
The following setup
trait OneTrait {
type Ty: AnotherTrait;
fn project() -> Self::Ty::Out;
}
trait AnotherTrait {
type Out;
}
produces the error
rustc 1.13.0 (2c6933acc 2016-11-07)
error[E0223]: ambiguous associated type
--> <anon>:3:17
|
3 | fn bar() -> Self::Bar::Out;
| ^^^^^^^^^^^^^^ ambiguous associated type
|
= note: specify the type using the syntax `<<Self as Foo>::Bar as Trait>::Out`
It would be great for the less explicit projection to work here.
cc @nikomatsakis
Note that the issue title may be overly specific; I haven't deeply investigated the cases where this kind of projection fails.
Aaron Turon at 2016-11-29 23:14:30
In my experience at least
A::B::Cnever works, although maybe bugs have been fixed that enables that recnetly?Alex Crichton at 2016-11-29 23:17:31
FWIW,
<<Self as Foo>::Bar as Trait>::Outcan be shortened to<Self::Ty as AnotherTrait>::Out.A::Bfor associated types currently works only ifAis a type parameter (includingSelf) that is known to have a trait with associated typeBas a bound.Vadim Petrochenkov at 2016-11-29 23:24:16
Possible duplicates: https://github.com/rust-lang/rust/issues/31372 and https://github.com/rust-lang/rust/issues/35711
Marco A L Barbosa at 2016-11-30 18:16:42
In terms of the compiler's implementation, this isn't really about projection. It's not actually getting that far. Rather, it fails when lowering the AST into types, which is the point where we have to pick a trait. @eddyb has been doing a lot of heroic work refactoring the type-end to remove that limitation, which is fairly tricky -- the problem is that to do it properly, one must reason about the where-clauses that are in scope and do trait selection, but to know what where-clauses are in scope, one must lower them, and that is what we are trying to do. To resolve this, @eddyb has been refactoring the compiler to cope with partially lowered sets of where-clauses, basically.
Niko Matsakis at 2016-12-20 16:14:11
So, is @eddyb's fix for this being developed openly somewhere it's possible to track progress (or help?) This issue is causing me some frustration, so I'd love to know what I could do to help resolve it.
neuronsguy at 2017-03-15 18:54:48
I think he wound up taking another approach. I'm not sure what's the shortest path here just now.
Niko Matsakis at 2017-03-16 17:27:02
Perhaps keying the
type_param_predicatesrequests on a type instead of just type parameters specifically, and treating failure to convert some types in bounds as an ambiguity, may work.Eduard-Mihai Burtescu at 2017-03-16 22:34:48
This is a huge paper cut for me: I have a lot of code of the form
<<<<F as E>::E as D>::D as C>::C as B>::B as A>::A>and it is completely unreadable to write methods on traits while having to skim through that.There are two cases where this cuts me:
- when I know that there isn't an ambiguity yet I have to disambiguate
- when I doubt if there is an ambiguity and might not want one, in which case I need to go through the whole trait hierarchy looking for it because... even though the error says "ambiguous" it doesn't bother telling me where the ambiguities are...
Having to disambiguate is the smaller paper cut. It would already be infinitely helpful if the error message would tell me if there is an actual ambiguity and where, or if it would tell me that there isn't an ambiguity.
gnzlbg at 2017-10-25 15:00:24
Maybe the problem is that what I understand by ambiguous (e.g. that two associated types are named equal) and what the compiler understands by ambiguous are different things.
gnzlbg at 2017-10-25 15:46:08
I've tried using syntax, that one would expect to work just fine, and have wound up with this issue. It's quite clear to any human that there exist no ambiguities in this code, yet the compiler unnecessarily requires extra (and ugly) syntax to accept the code. This is extremely inconvenient.
Joshua Barretto at 2018-03-22 17:38:46
I'm not sure if chiming in and saying "me too" at this point is more annoying than helpful, but me too :)
I think this one's hard on novice Rustaceans because we're interpreting the situation as human error, as if we've unintentionally made the situation ambiguous and there's something we can do to correct it.
Alexander Litty at 2018-04-17 04:57:54
I would also love this. I've been "shortening" it like this, but this way there is an extra associated type that structs have to implement for no reason:
trait OneTrait { type Ty: AnotherTrait<Out=Self::Oy>; type Oy; fn project() -> Self::Oy; } trait AnotherTrait { type Out; }Ken Reed at 2018-05-05 10:36:48
At the very least, the error message should be improved; it gives bad advice: [Playground]
neptunepink at 2018-06-28 02:24:48
Is this issue one that someone could take on as a first issue for fixing the compiler or is this still in the area of experts? It seemed like something quite hard a while ago, but maybe progress has been made? If this is something easier than it used to be, could someone point me to the area of code that would need to be fixed?
ZacLiveEarth at 2019-05-09 19:41:15
Sadly, not enough progress has been made for this to be readily doable yet.
Eduard-Mihai Burtescu at 2019-05-13 19:31:44
Has there been any progress on this front? Was just curious if there was/will be/is planned to have an update of some sort.
Benjamin Xu at 2019-09-05 19:40:14
Will chalk resolve this?
Jonas Platte at 2020-08-10 10:47:21
Still happens with Rust 1.45.2
Following code:
pub struct MyStruct { rng : rand::Rng::SmallRng }Outputs:
error[E0223]: ambiguous associated type --> src\algorithm\m_struct.rs:11:11 | 11 | rng : rand::Rng::SmallRng, | ^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(dyn rand::Rng + 'static) as Trait>::SmallRng`Is there any workaround?
Piotr Kosek at 2020-08-10 14:33:40
chalk will not resolve this without more work, though we did have some experimental ideas for how to resolve it.
Niko Matsakis at 2020-08-17 18:02:10
This also is a problem with non-nested types:
trait T { type M : Sized; } struct S { some_var: u32 } impl T for S { type M = u32; } fn main() { let v: S::M = 0; }Output:
error[E0223]: ambiguous associated type --> src/main.rs:18:12 | 18 | let v: S::M = 0; | ^^^^ help: use fully-qualified syntax: `<S as Trait>::M` error: aborting due to previous errorYuri6037 at 2021-07-26 21:36:45
I'm not super convinced. I think it's reasonable to ask
rustc_resolveto give an initial "associated item or variant" lookup or something. If it's resolved without ambiguity, an error should not be emitted to the user.This kind of resolution is easy victim to upstream associated item changes. However for ergonomics it might be worth it?
Charles Lew at 2021-09-10 10:09:05
At least give me an error that tells me what to do? Because the current output is insanely bad for developer productivity; It should be telling me what options it thinks it has and why its considered ambiguous.
Duane King at 2021-09-11 16:35:29
Any progress on this?
Vladas Zakrevskis at 2022-04-07 00:58:47
i've been dancing around this issue in some form or another for a few years and i only just realized that another workaround for this is writing a type alias to at least hide the process of walking rustc through the type relationships:
pub trait ATrait { type B: BTrait; } pub trait BTrait { type C: CTrait; } pub trait CTrait {} // this works! i can go simplify several crates now. yay. pub type AToC<A> = <<A as ATrait>::B as BTrait>::C; pub fn project<A: ATrait>() -> AToC<A> { panic!("C"); }this is similar to tiby312's comment a few years ago but i hadn't fully considered that the type alias could be freestanding and organized elsewhere as appropriate.
iximeow at 2023-08-09 21:49:42
Just chiming in that it would be really nice if this was possible. I came up with a nice refactor that turned out to be not practical because it's not ergonomic to use a type nested in the trait in a trait implementation. It would be really nice if this was possible.
Thijs Cadier at 2024-12-01 10:28:32
Am I right in thinking that this is caused by rustc not having a notion of 'trait variables' (akin to type variables) within its solver? I've added support for trait variables to my own lang and it seems to be pretty reliably capable of arbitrary associated type projection like this.
Joshua Barretto at 2024-12-01 13:22:52