Skip to content

Sugared paths to associated types via non-variable types #19559

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

Closed
nrc opened this issue Dec 5, 2014 · 6 comments
Closed

Sugared paths to associated types via non-variable types #19559

nrc opened this issue Dec 5, 2014 · 6 comments
Labels
A-associated-items Area: Associated items (types, constants & functions)

Comments

@nrc
Copy link
Member

nrc commented Dec 5, 2014

E.g., Foo::A where Foo is a struct and A is an associated type on one of its impls, or int::A. (Currently T::A only works where T is a type parameter or Self).

@nrc nrc added the A-associated-items Area: Associated items (types, constants & functions) label Dec 5, 2014
bors added a commit that referenced this issue May 12, 2015
…atsakis

It is currently broken to use syntax such as `<T as Foo>::U::static_method()` where `<T as Foo>::U` is an associated type. I was able to fix this and simplify the parser a bit at the same time.

This also fixes the corresponding issue with associated types (#22139), but that's somewhat irrelevant because #22519 is still open, so this syntax still causes an error in type checking.

Similarly, although this fix applies to associated consts, #25046 forbids associated constants from using type parameters or `Self`, while #19559 means that associated types have to always have one of those two. Therefore, I think that you can't use an associated const from an associated type anyway.
@steveklabnik
Copy link
Member

Triage: trying to figure out what this was about:

Foo::A where Foo is a struct and A is an associated type on one of its impls,

struct Foo;

impl Foo {
    type A = i32;
}

errors:

hello.rs:6:5: 6:18 error: associated types are not allowed in inherent impls [E0202]
hello.rs:6     type A = i32;
               ^~~~~~~~~~~~~
hello.rs:6:5: 6:18 help: run `rustc --explain E0202` to see a detailed explanation

So I'm either misunderstanding something, or things have changed since this was opened. @nrc , which is it?

@nrc
Copy link
Member Author

nrc commented Jan 1, 2016

e.g.,

trait T {
    type U;
}

struct S;

impl T for S {
    type U = i32;
}

fn main() {
    let _: <S as T>::U = 43;  // Works today.
    let _: S::U = 43;  // Doesn't work today but should, this issue.
}

Today, we get an ambiguity error, but there is no ambiguity here.

@rphmeier
Copy link
Contributor

rphmeier commented Jan 1, 2016

There is some potential ambiguity here.
Assuming that S is some type visible to both crates, and you pulled in some crate with code like this:

pub trait T2 {
    type U;
}

impl T2 for S {
    type U = isize;
}

The compiler can't determine if the type is i32 or isize for the code you've posted above. I've seen discussion in a few other issues/RFCs that pulling in some specific combination of crates shouldn't mysteriously break code which worked previously, so I think this is something to consider. Of course, if you can prove that S is not visible outside the current crate, it should be possible to determine that there is only one resolution for the type S::U.

@Mark-Simulacrum
Copy link
Member

I'm not sure this is worth implementing.

Making Struct::Associated work when non-ambiguous would mean that adding a trait impl to a struct or making a struct public would both cause other code to not compile, I think, which seems unhelpful/wrong.

@Mark-Simulacrum
Copy link
Member

Closing. I think that the decisions that need to be made with regards to ambiguity make closing this for the time being the best option. It's unclear that there are any significant wins, especially since this feature would make it more confusing to see T::U: T could now be anything (struct, enum, union, or trait) and to find U you have to look through all of T's impls, which seems unfortunate.

This works already with bounds that clear up ambiguity, as below:

struct T;

trait A {
    type Type;
    fn create(&self) -> Self::Type;
}

impl A for T {
    type Type = i32;
    fn create(&self) -> Self::Type {
        10
    }
}

fn t<X: A>(x: X) -> X::Type {
    x.create()
}

fn main() {}

@TitanThinktank
Copy link

TitanThinktank commented Dec 3, 2019

thanks to nrc commented from Jan 1, 2016
This line
let _: <S as T>::U = 43; // Works today.
it did wonders for me, i could define a type inside trait and also make a member variable of that inside the struct that trait was implemented in, an amazing feature.

lnicola pushed a commit to lnicola/rust that referenced this issue Apr 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-associated-items Area: Associated items (types, constants & functions)
Projects
None yet
Development

No branches or pull requests

5 participants