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

Tracking issue for `associated_consts` feature #29646

Closed
aturon opened this issue Nov 5, 2015 · 103 comments
Closed

Tracking issue for `associated_consts` feature #29646

aturon opened this issue Nov 5, 2015 · 103 comments

Comments

@aturon
Copy link
Member

@aturon aturon commented Nov 5, 2015

The feature is currently quite buggy, but this issue tracks its eventual stabilization.

Shortcomings of the current implementation

Associated consts in const expressions must be concrete

Associated consts can only be used in const contexts if their input types are fully concrete. That is, this works:

trait Foo {
     const X: usize;
}

impl Foo for () {
     const X = 0;
}

let y: [i32; <() as Foo>::X];

But this does not work:

fn foo<T: Foo>() {
    let y: [i32; <T as Foo>::X];
}

Associated consts are never object safe

Associated consts make a trait non-object-safe. There is no way to bound the const where Self: Sized, nor to specify the const when creating the object.

trait Foo {
    const FOO: i32;
}

// Not allowed:
Box<Foo<FOO = 0>>

trait Bar {
    // Not allowed
    const BAR: i32 where Self: Sized;
}

Associated consts referencing other associated consts have spurious destructor warnings

This works:

trait Foo {
    const FOO: Option<i32>;
}

trait Bar: Foo + 'static {
    const BAR: Option<i32> = <Self as Foo>::FOO;
}

But this does not, because we (unnecessarily) assume the const could be a variant that runs a destructor:

trait Foo {
    const FOO: Option<String>;
}

trait Bar: Foo + 'static {
    const BAR: Option<String> = <Self as Foo>::FOO;
}
homu added a commit to autumnai/collenchyma that referenced this issue Dec 2, 2015
Move to stable

This PR removes unnecessary use of feature flags that bar using Rust on stable([1])([2]) compilers.

Reasons being:
* associated consts (Tracking issue: rust-lang/rust#29646) are currently buggy and can be replaced by an fn in that case.
* associated_type_defaults can be removed without breakage
* unboxed_closures can be removed without breakage
* StaticMutex has an uncertain future (rust-lang/rust#27717) and can be emulated in that case by using `lazy_static!` (correct me if I'm wrong)

Finally, I must admit that I didn't get the test suite running quickly.

([1]) Outstanding: this doesn't _quite_ work on stable yet, as some APIs in use are currently making their way through beta, so they are not feature gated, but also not available in 1.4.0. 1.5.0 beta works and as 1.5.0 is 2 weeks away, this is probably not worth the effort.
([2]) rblas is not on stable yet, see mikkyang/rust-blas#12 for that. You can use that version of rust-blas by checking it out from my https://github.com/skade/rust-blas/ and dropping the following `.cargo/config` in your repository:

```
paths = ["/path/to/rblas/checkout"]
```
@raindev
Copy link
Contributor

@raindev raindev commented Feb 13, 2016

I'm curious about the reasons behind this feature. Why aren't ordinary functions good enough for the same purpose? Given that Rust have default methods it shouldn't be much less ergonomic. And combination of monomorphisation and static lifetimes should converge any difference in terms of performance.

@ketsuban
Copy link
Contributor

@ketsuban ketsuban commented Feb 16, 2016

One notable case is that of the Zero and One traits, which exist solely to confer their constant value to the types which implement them. With associated constants they would be redundant, as Sum and Mul would include the additive and multiplicative identities.

@raindev
Copy link
Contributor

@raindev raindev commented Feb 16, 2016

@ketsuban how would it be different than including zero and one as functions into Sum and Mul traits?

@raindev
Copy link
Contributor

@raindev raindev commented Feb 16, 2016

Having skimmed through #27739 it looks like there're opinions about the concepts of "zero" and "one" as functions as it may give additional flexibility.

@mitaa
Copy link
Contributor

@mitaa mitaa commented Feb 16, 2016

@raindev

Why aren't ordinary functions good enough for the same purpose?

https://github.com/rust-lang/rfcs/blob/master/text/0195-associated-items.md#user-content-expressiveness

@vberger
Copy link
Contributor

@vberger vberger commented Feb 16, 2016

The use of associated consts could make things like bitflags! more pretty in my opinion, by scoping the consts in the name of the bitflags struct, much like enum variants are scoped in the name of the enum.

@Roxxik
Copy link

@Roxxik Roxxik commented Feb 19, 2016

would love to use associated consts for array sizes for example: http://is.gd/VSee6B

struct Something {
    inner: [u8; Something::LENGTH]
}

but this will leave me at E0250

@dhardy dhardy mentioned this issue Feb 23, 2016
0 of 1 task complete
@Robbepop
Copy link
Contributor

@Robbepop Robbepop commented Mar 1, 2016

I'm curious about the reasons behind this feature. Why aren't ordinary functions good enough for the same purpose?

I am not sure about this but I think that associated constants could allow us compile time execution for things similar to non-type template parameters as in C++ which are quite useful. Using functions wouldn't work in the example below since Rust currently has no mechanism to detect if a function can be evaluated at compile-time (constexpr as in C++ or even templates).

Example:
https://gist.github.com/Robbepop/da73db721c22492616f6

If the example above really works (haven't tested it, yet) things like BitFlag or the shown BigInt could be implemented very efficiently - not using the heap at all!

@Boddlnagg
Copy link
Contributor

@Boddlnagg Boddlnagg commented May 28, 2016

Is there any ETA on the stabilization of this feature? It would be really useful for something which I'm currently experimenting with, namely the implementation of Windows COM interop: One could add a trait that exposes each interface's GUID and/or class ID as constants, then e.g. this API could be mapped to Rust in a way that takes the to-be-activated class as a type parameter that implements said trait.

Of course I can work on this using nightly, but it would be nice to have some information whether the feature is going to be stabilized in the near future!

@nrc
Copy link
Member

@nrc nrc commented Aug 17, 2016

Should we block on #34344? Are there other known bugs? Are there design questions to resolve here?

@letheed
Copy link
Contributor

@letheed letheed commented Sep 9, 2016

There was a question on the forum here. Looks like a bug to me.

@hauleth
Copy link
Contributor

@hauleth hauleth commented Nov 7, 2016

What is status or what would need to be done to stabilize this feature? It would be really helpful in Octavo as it would allow me to provide HMAC without any heap allocations.

@seanmonstar
Copy link
Contributor

@seanmonstar seanmonstar commented Nov 7, 2016

@hauleth take a look at the associated-items issues. That contains many of the bugs that exist with associated constants. I imagine many of them would need to be fixed before anyone could consider this feature "stable".

@brson
Copy link
Contributor

@brson brson commented Jan 11, 2017

How can we accelerate this? This is a major feature and it doesn't appear to be moving or have a champion.

This is used by Rocket.

@brson brson added the I-nominated label Jan 11, 2017
@brson
Copy link
Contributor

@brson brson commented Jan 11, 2017

Just nominating to put it in front of eyeballs again.

@steveklabnik
Copy link
Member

@steveklabnik steveklabnik commented Jan 11, 2017

My understanding is that this is waiting on a re-do of const evaluation in the compiler, since it's so buggy. @eddyb ?

@eddyb
Copy link
Member

@eddyb eddyb commented Jan 11, 2017

"Buggy" is not the best way to put it IMO, "barely does anything at all" is far closer.
@brson You can consider @solson, @oli-obk (both miri) and me (rustc) as unofficial champions (for the past several months) for const-eval-related areas.

@eddyb eddyb mentioned this issue Jan 11, 2017
3 of 3 tasks complete
@steveklabnik
Copy link
Member

@steveklabnik steveklabnik commented Aug 28, 2017

Yes, it will be in 1.20.

@nwin
Copy link
Contributor

@nwin nwin commented Aug 29, 2017

Maybe I’m not seeing the point but as long as “Associated consts in const expressions must be concrete” is still a restriction I do not see any use of associated constants in traits.

Yet you can add them such that all of the error messaged presented in #32344 are still very there and very misleading.

Shouldn’t one simply forbid associated constants in traits unless that restriction is lifted? I dont’t think that it was a good idea merge #42809 (i.e. remove the feature gate) with a feature in such an incomplete state.

@eddyb
Copy link
Member

@eddyb eddyb commented Aug 29, 2017

@nwin It's not "in const expressions" - but rather "in types", i.e. array types.

@frehberg
Copy link
Contributor

@frehberg frehberg commented Sep 7, 2017

Is there any plan to introduce LEN (or similar attribute) as associated const for the built-in rust-primitives 'arrray' or 'slice'? , for example

const N : usize = b"my_byte_string"::LEN;

or

is there any plan to declare std::intrinsics::size_of_val(v) as const-fn(?) enabling somehing like:
#![feature(core_intrinsics)]
const N: usize = unsafe { std::intrinsics::size_of_val(b"my_byte_string") };

@eddyb
Copy link
Member

@eddyb eddyb commented Sep 7, 2017

@frehberg When const generics are implemented you will be able to do that yourself, for example with an impl<T, const N: usize> MyLenTrait for [T; N]

@robinst
Copy link
Contributor

@robinst robinst commented Sep 28, 2017

Anyone landing here from googling "associated const", this was released in Rust 1.20, see the announcement: https://blog.rust-lang.org/2017/08/31/Rust-1.20.html

@robinst
Copy link
Contributor

@robinst robinst commented Sep 28, 2017

Also, if anyone is looking for the documentation of this, it's here: https://doc.rust-lang.org/stable/reference/items.html#associated-constants

(It was surprisingly hard to find.)

tokenrove added a commit to tokenrove/fixie-trie that referenced this issue Oct 30, 2017
The last time I looked at this, rust-lang/rust#29646 wasn't finished,
but now it is.  This avoids the possibility of a pathological
implementer of FixedLengthKey returning varying values for levels.

(Thanks Raph!)
@SergioBenitez
Copy link
Contributor

@SergioBenitez SergioBenitez commented Feb 12, 2018

Shouldn't equality bounds be possible with associated consts? The following does not compile today:

trait Foo {
    const BAR: usize;
}

// error: expected type, found `10`
fn f<T: Foo<BAR = 10>>() { }

The original associated items RFC makes it clear that this should be possible. I'm wondering: was this simply forgotten about? Or perhaps there are/were complications with implementing this?

@SergioBenitez
Copy link
Contributor

@SergioBenitez SergioBenitez commented Feb 16, 2018

Furthermore, using an associated const as an array size does not appear to work:

pub trait Can {
    const SIZE: usize;
}

fn f<T: Can>(t: T) {
    // error[E0277]: the trait bound `T: Can` is not satisfied
    let x = [0u8; <T as Can>::SIZE];
}

There error message is clearly wrong, so this is either a bug in rustc or unimplemented functionality resulting in a bogus error message.

@shepmaster
Copy link
Member

@shepmaster shepmaster commented Feb 16, 2018

using an associated const as an array size

Probably related to #42863, #44168, #44774 ?

@gnzlbg
Copy link
Contributor

@gnzlbg gnzlbg commented Feb 17, 2018

Furthermore, using an associated const as an array size does not appear to work:

This usage of associated const was not stabilized, as documented in this issue (it doesn't work on nightly either, and probably won't work until const-generics implementation improves).

@gnzlbg
Copy link
Contributor

@gnzlbg gnzlbg commented Jun 5, 2018

I don't know if this is the same issue that @eddyb mentioned here: #29646 (comment)

trait Foo { const A: usize; }
fn foo<F: Foo>(f: F) {
    const B: usize = F::A; // ERROR
    let b = F::A; // OK
}
@eddyb
Copy link
Member

@eddyb eddyb commented Jun 5, 2018

@gnzlbg Those are two items nested in eachother, we don't allow "inheriting" type parameters in such a situation and it'd be a significant language change to start doing that.
IOW, what you wrote is more or less equivalent to:

const __HIDDEN_B: usize = F::A;
fn foo<F: Foo>(f: F) {
    use self::__HIDDEN_B as B;
}

(and this is not in any way, shape, or form, specific to const or associated const)

@ghost
Copy link

@ghost ghost commented Jun 26, 2018

Having const fn is this feature still required ? Of course it'd require to have const fn in traits as well.
(For now no array size can be given using either associated const or const fn)

((Or one could be the desugaring'of the other ))

@steveklabnik
Copy link
Member

@steveklabnik steveklabnik commented Jun 26, 2018

@zpgaal this feature is implemented and stable, so regardless of it being "required", it has to stay!

@vks
Copy link
Contributor

@vks vks commented Jul 11, 2018

@steveklabnik It seems like rustdoc does not generate documentation for associated constants in structs. Is this a bug?

@SimonSapin
Copy link
Contributor

@SimonSapin SimonSapin commented Jul 11, 2018

@vks I cannot reproduce this. rustdoc a.rs with the code below does document the constant.

pub struct Foo;

impl Foo {
    pub const BAR: u32 = 7;
}
@gnzlbg
Copy link
Contributor

@gnzlbg gnzlbg commented Jul 11, 2018

@SimonSapin I think the problem is:

pub struct Foo;

impl Foo {
    /// This doc comment won't be shown anywhere.
    pub const BAR: u32 = 7;
}
@SimonSapin
Copy link
Contributor

@SimonSapin SimonSapin commented Jul 11, 2018

Oh I see. Please file a bug separately?

@vks
Copy link
Contributor

@vks vks commented Jul 11, 2018

Oh I see. Please file a bug separately?

See #52260.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
You can’t perform that action at this time.