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 const generics (RFC 2000) #44580

Open
withoutboats opened this Issue Sep 14, 2017 · 69 comments

Comments

@withoutboats
Copy link
Contributor

withoutboats commented Sep 14, 2017

Tracking issue for rust-lang/rfcs#2000

cc @eddyb

Blocking stabilization:

  • Design:
    • Resolving ordering of const and type parameters, with default parameters
    • Decide what the best UX / implementation cost balance is for unifying abstract const expressions.
    • How we determine well formedness of const expressions.
  • Implementation
  • Documentation
    • rustc guide
@eddyb

This comment has been minimized.

Copy link
Member

eddyb commented Sep 15, 2017

#44275 added a ConstEvaluatable predicate, and WF([T; expr]) now requires ConstEvaluatable(expr), as expr is lazily evaluated (even if it's just an integer literal). Fulfilling this predicate requires the expression to evaluate successfully, while normalization ignores the error and simply leaves the Unevaluated expression it found, untouched, which is more or less what happens with associated type projections. I expect the same system to scale to const generics.

@EpicatSupercell has expressed interest in working on this, I'll mentor them through the initial implementation. However, we can't go too far because of the limitations described in #44275.

That is, we need @nikomatsakis' lazy normalization to allow constant expressions embedded in types to observe the bounds in scope (from the function / type definition / impl / etc. item they're in), without producing cyclic dependencies half the time.

@eddyb

This comment has been minimized.

Copy link
Member

eddyb commented Sep 18, 2017

Implementation waypoints (for more direct mentoring, seek @eddyb on Gitter or eddyb on IRC):

  • Declaration / Syntax:
  • Declaration / Semantics
    • Data structures: ty::Generics - add const parameters alongside type ones
    • Conversion from HIR: generics_of - create ty::ConstParameterDef from hir::ConstParam
  • Use / Name Resolution
    • Data structures: Def - add a variant for const parameters
    • Name resolution pass: with_type_parameter_rib - support both type and const generics
  • Use / Semantics
    • ConstVal - add Param variant akin to ty::TyParam
    • Conversion from HIR: TyArray with a length that's an ExprPath that resolved to Def::ConstParam should use ConstVal::Param instead of ConstVal::Unevaluated - in a similar fashion to how Def::TyParam turns into ty::TyParam
    • subst::Kind - support &ty::Const and check as_const as well in where places where as_type and as_region are checked
  • Inference

Note that all of this should allow impl<T, const N: usize> Trait for [T; N] {...}, but not actually passing a constant expression to a type/function, e.g. ArrayVec<T, 3>.

@eddyb eddyb added the E-mentor label Sep 18, 2017

@eddyb eddyb self-assigned this Sep 18, 2017

@jplatte

This comment has been minimized.

Copy link
Contributor

jplatte commented Sep 18, 2017

I'd like to take a stab at this :)

@samsartor

This comment has been minimized.

Copy link

samsartor commented Oct 26, 2017

@jplatte @eddyb Any news on this?

@jplatte

This comment has been minimized.

Copy link
Contributor

jplatte commented Oct 26, 2017

@samsartor there was a refactoring that had to be done before the main implementation work. That is now almost done (I'm waiting for feedback currently). I don't actually know how much work there is after that. Parsing const params was what I started with initially, before the refactoring. It's not done but I should be able to get that done relatively soon.

@EdorianDark

This comment has been minimized.

Copy link
Contributor

EdorianDark commented Nov 6, 2017

@jplatte It would be nice, if you could link the pull request. I was not able to find it.

@jplatte

This comment has been minimized.

Copy link
Contributor

jplatte commented Nov 6, 2017

There is no PR yet. All my work can be found here.

@RobertWHurst

This comment has been minimized.

Copy link

RobertWHurst commented Nov 6, 2017

Nice work so far @jplatte 🍻

@jplatte

This comment has been minimized.

Copy link
Contributor

jplatte commented Nov 11, 2017

There is now a PR for the groundwork (Generics refactoring): #45930

@huhlig

This comment has been minimized.

Copy link

huhlig commented Nov 17, 2017

I think this is already included but it would be good to handle the C++ style folding for handling linear algebra style n dimensional arrays with varying lengths, I.E. a 4x4 [[f64;4];4]or a 4x3x5x6 dimensional array [[[[f64;6];5];3];4] and be able to properly wrap and generate specialized methods for both it AND proper trait implementations for scalars properly dimensioned vectors, etc. See https://gist.github.com/huhlig/8b21850b54a75254be4b093551f8c2cb for a rudamentary example.

@Ixrec

This comment has been minimized.

Copy link
Contributor

Ixrec commented Nov 18, 2017

I don't recall anyone proposing fold expressions for Rust before, much less as part of this RFC. But since this is Rust, is there any reason we couldn't implement fold expressions as an ordinary macro, rather than new dedicated syntax?

@cuviper

This comment has been minimized.

Copy link
Member

cuviper commented Sep 5, 2018

_phantom: [(), N],

I assume you meant [(); N], but this will only work for usize.

I think it would make sense to have a special marker::PhantomConst allowing any const type.

@Ekleog

This comment has been minimized.

Copy link

Ekleog commented Sep 6, 2018

Hmm… Re-reading the RFC with the latest comments in mind, I'm wondering: would something like this be allowed?

struct Foo<T, const V: T> {
    _phantom: PhantomConst<T, V>,
}

I can't see it being banned anywhere, but would have thought it'd deserve at least an example.

@varkor

This comment has been minimized.

Copy link
Member

varkor commented Sep 6, 2018

@Ekleog: as far as I'm aware, const parameter types may not depend on type parameters initially (though it would definitely make sense for an extension). (The implementation is trickier if we allow this, so it makes sense to start with the simplest version.)

@Zauberklavier

This comment has been minimized.

Copy link

Zauberklavier commented Sep 7, 2018

How is the progress on this? Do we know an approximate time when this should hit nightly?

@GabrielMajeri

This comment has been minimized.

Copy link
Contributor

GabrielMajeri commented Sep 7, 2018

@Zauberklavier As soon as this pull request is done. To quote from it:

There's a long way to go

@eddyb

This comment has been minimized.

Copy link
Member

eddyb commented Sep 7, 2018

@newpavlov I assumed constant parameters would be allowed without being used in fields.
The reason type parameters must be used is because of variance, but constants don't have this issue.

@withoutboats

This comment has been minimized.

Copy link
Contributor

withoutboats commented Sep 7, 2018

@eddyb that's what I recall from the RFC discussion also.

@Ekleog

This comment has been minimized.

Copy link

Ekleog commented Sep 9, 2018

@varkor So this means PhantomConst proposed by @cuviper cannot exist in the current state of this RFC… right? though latest comments appear to point that there is no need for PhantomConst anyway.

@burdges

This comment has been minimized.

Copy link

burdges commented Sep 21, 2018

Do const parameters impact the variance of type parameters they involve?

@eddyb

This comment has been minimized.

Copy link
Member

eddyb commented Sep 22, 2018

Currently I believe const generics can't have type parameters in their type.

@rodrimati1992

This comment has been minimized.

Copy link

rodrimati1992 commented Nov 2, 2018

I am not clear on what the first working version of this will be able to do.

For example whether the code in this comment would compile:
rust-lang/rfcs#2581 (comment)

If that code compiled,it would be a way to enforce constraints for constants before getting a syntax for it.

@eddyb

This comment has been minimized.

Copy link
Member

eddyb commented Nov 5, 2018

@rodrimati1992 You can probably just do (): IsTrue<{N < 128}> without a separate type.
I guess you want to reuse the constraint and have it actually work? (because copying the N < 128 expression won't make it work, initially)
You could use trait Lt128<const N: usize> = IsTrue<{N < 128}>;, I guess.
There's also the option of just writing where [(); 128 - N],, I think (but I'm not sure we guarantee that will panic).

@rodrimati1992

This comment has been minimized.

Copy link

rodrimati1992 commented Nov 5, 2018

@rodrimati1992 You can probably just do (): IsTrue<{N < 128}> without a separate type.
I guess you want to reuse the constraint and have it actually work? (because copying the N < 128 expression won't make it work, initially)
You could use trait Lt128<const N: usize> = IsTrue<{N < 128}>;, I guess.
There's also the option of just writing where [(); 128 - N],, I think (but I'm not sure we guarantee that will panic).

So,with trait aliases I could rewrite is to this?:

trait AssertLessThan128<const N:usize>=
    Assert<{N<=128}, (
        Str<"uint cannot be constructed with a size larger than 128,the passed size is:",
        Usize<N>>
    ) >;

The idea with the Assert<cond B:bool,Msg> trait is using a type error to print an error message embedded in a type,which in the case of AssertLessThan128 is:

(Str<"uint cannot be constructed with a size larger than 128,the passed size is:",Usize<N>>)

which I expect to be more helpful than where [(); 128 - N],,since it tells you in the error message why the compile-time error happened.

@eddyb

This comment has been minimized.

Copy link
Member

eddyb commented Nov 5, 2018

You can also do if !(N < 128) { panic!("...") } in a constant, I think?

@rodrimati1992

This comment has been minimized.

Copy link

rodrimati1992 commented Nov 5, 2018

I thought the std::fmt architecture is not going to be there until const trait constraints (or something similar) arrive?

With this thing you can have error messages with multiple values in it (embedded in types).

Maybe it's better to wait for const generics to talk about this,since it'll be easier to show executable examples.

@Nemo157

This comment has been minimized.

Copy link
Contributor

Nemo157 commented Nov 5, 2018

@rodrimati1992 see https://github.com/rust-lang/rfcs/blob/master/text/2345-const-panic.md, there's going to be a special case to get const panic!() before it would be possible via other features (at a guess it probably won't allow custom formatting of values at first).

@eddyb

This comment has been minimized.

Copy link
Member

eddyb commented Nov 5, 2018

@rodrimati1992 Ahh, I see, that's indeed a clever trick!

@quadrupleslap

This comment has been minimized.

Copy link

quadrupleslap commented Jan 10, 2019

What's the status of this?

@HadrienG2

This comment has been minimized.

Copy link

HadrienG2 commented Jan 10, 2019

Next step is still #53645 AFAIK.

@yodaldevoid

This comment has been minimized.

Copy link
Contributor

yodaldevoid commented Jan 10, 2019

This is correct. To give a quick update for those not following the PR #53645, const generics have compile and work in at least one simple usecase. What remains is finishing up codegen for other usecases, including const generics in arrys, and some error output cleanup. After that, the PR should be ready merge and people can start playing with it.

@jeffvandyke

This comment has been minimized.

Copy link

jeffvandyke commented Jan 16, 2019

Might be off-topic, but will this allow a variant or fork of Chunks and related methods to have Item be a compile-time-fixed-size array instead of a slice? This would allow a for loop to destructure/bind to an irrefutable pattern that mapped the elements in the chunk to variables, such as for (first, second) in arr.chunks(2) which currently fails, and I'm guessing (without any justification admittedly) that it would allow more optimization in certain use cases.

@vadixidav

This comment has been minimized.

Copy link
Contributor

vadixidav commented Jan 16, 2019

@jeffvandyke You might be thinking of ChunksExact specifically. Such a change would be API-breaking, so it can't be done. We could add new APIs that give array references in the future, but we can't break existing ones.

@sdroege

This comment has been minimized.

Copy link
Contributor

sdroege commented Jan 16, 2019

@jeffvandyke You might be thinking of ChunksExact specifically. Such a change would be API-breaking, so it can't be done. We could add new APIs that give array references in the future, but we can't break existing ones.

I'm only waiting for this to be implemented and stabilized before proposing a PR that adds such API in addition to ChunksExact and its variants :)

The runtime and compile-time variants both have their use-cases, you don't always know your chunk size ahead of time. Optimization-wise, if you use ChunksExact with a constant it should be more or less the same according to my testing. The compiler can optimize away all bounds checks.

@shepmaster

This comment has been minimized.

Copy link
Member

shepmaster commented Jan 16, 2019

to be implemented and stabilized

I'd suggest not waiting for stabilization as such an API would be one more good use to help exercise this feature for stabilization.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment