Stream: t-compiler/const-eval

Topic: const_trait_impl's syntax


view this post on Zulip fee1-dead (Aug 17 2021 at 06:22):

I have been doing a lot of work with const_trait_impl, and I begin to realize the syntax proposed by the RFC is not the best.

We currently have impl const Trait, but we don't have T: const Trait. This feels inconsistent when you have to look for T: Trait as well as T: ?const Trait to find non-const bounds (and the former can be acually a const bound when on a const function!)

I really like T: const Trait, because we can now put constness as a part of a TraitRef. So the rest of the world becomes pretty consistent: impl TraitRef the constness is part of TraitRef and not part of the impl's header. We could disallow other places for now such as <T as const Trait>::blah(), and it would make other things easier to come: const fn pointer, const dyn traits...

cc @oli

view this post on Zulip RalfJ (Aug 17 2021 at 08:54):

and it would make other things easier to come: const fn pointer, const dyn traits...

Are you referring to the issues raised here and the alternative described here?

view this post on Zulip RalfJ (Aug 17 2021 at 08:58):

If yes, I think I agree. However, there are two different things you could be meaning here:

const fn do_add<T: const Add>(x: T, y: T) -> T { x+y }

Does this mean that the function always requires a impl const Add or just when called in a context that might be evaluated at compiletime? IOW, does this build?

#[derive(Copy,Clone)]
struct MyType(i32);

impl Add for MyType {...}

// Runtime-only function!
fn foo(x: MyType) {
  do_add(x, x);
}

(This is related to ?const Add in the RFC)

view this post on Zulip oli (Aug 17 2021 at 09:49):

yea, the one concern I have with this is fn foo<T: const Trait>() and what that's supposed to mean. In full "const effect" syntax we want something like a generic parameter: for<const C: bool> const<C> fn foo<T: const<C> Trait>()so we can use the functions constness to change whether the bound is const

view this post on Zulip oli (Aug 17 2021 at 09:51):

we may one day want to allow fn foo<T: const Trait>() { let x = const { T::method() } }, so the plain const bound syntax is not clearly the right thing to me

view this post on Zulip RalfJ (Aug 17 2021 at 10:28):

fn foo<T: const Trait>() and what that's supposed to mean

as I keep saying -- I think that whatever it means, it should be consistent with fn foo(x: &dyn const Trait) (and likewise for T: Trait and &dyn Trait)

view this post on Zulip RalfJ (Aug 17 2021 at 10:29):

oli said:

we may one day want to allow fn foo<T: const Trait>() { let x = const { T::method() } }, so the plain const bound syntax is not clearly the right thing to me

not sure what "the plain const bound syntax" is, but I guess you are bringing this up as an argument for not accepting the code in my example above?

view this post on Zulip oli (Aug 17 2021 at 10:46):

if your example compiles, then the const in const Add depends on the call site. That makes little sense for non-const fn, so imo we should treat const Trait bounds as "always require constness" and figure something out that is not as horrible as the "effect syntax"

view this post on Zulip oli (Aug 17 2021 at 10:46):

RalfJ said:

I guess you are bringing this up as an argument for not accepting the code in my example above?

yes

view this post on Zulip oli (Aug 17 2021 at 10:47):

"the plain const bound syntax" -> const Trait in bounds

view this post on Zulip RalfJ (Aug 17 2021 at 11:20):

That makes little sense for non-const fn,

Ah okay; originally I thought the plan might be to only allow this on const fn

view this post on Zulip RalfJ (Aug 17 2021 at 11:20):

figure something out that is not as horrible as the "effect syntax"

didn't you propose const? for this?

view this post on Zulip oli (Aug 17 2021 at 11:32):

well, I did propose ?const with the meaning like ?Sized (so can be const or not, we don't care in any situation). We could come up with arbitrary other syntax, but I don't think we should re-use ?const in a way that means "const if in const context, otherwise not", as that seems to differ too much from how ?Sized works

view this post on Zulip oli (Aug 17 2021 at 11:32):

That said. idk what dyn const Trait even means outside of const contexts

view this post on Zulip RalfJ (Aug 17 2021 at 11:33):

oli said:

That said. idk what dyn const Trait even means outside of const contexts

it means the vtable comes from an impl const Trait

view this post on Zulip RalfJ (Aug 17 2021 at 11:33):

whether that's useful though is another question^^

view this post on Zulip oli (Aug 17 2021 at 11:33):

RalfJ said:

whether that's useful though is another question^^

ok, yea I know what it means, but what it's for is unclear

view this post on Zulip oli (Aug 17 2021 at 11:33):

unless we have some guarantees that const bounds bring that we can't have otherwise

view this post on Zulip oli (Aug 17 2021 at 11:33):

but even then

view this post on Zulip oli (Aug 17 2021 at 11:34):

if we make it "const if in const context" if used on const fn args, what do we do on non-const fn?

view this post on Zulip oli (Aug 17 2021 at 11:35):

mixing the "must have an impl const Trait" with "must have an impl const Trait if in const context" seems like an aweful situation

view this post on Zulip oli (Aug 17 2021 at 11:35):

If we forbid it on non-const fn, this problem is resolved

view this post on Zulip oli (Aug 17 2021 at 11:36):

but then we have no syntax for actually requiring a const Trait bound outside of const fn used in a const context

view this post on Zulip oli (Aug 17 2021 at 11:37):

which is fine if we never need such a feature, but we should at least consider if we want to throw away the obvious syntax for that forever

view this post on Zulip RalfJ (Aug 17 2021 at 11:38):

oli said:

If we forbid it on non-const fn, this problem is resolved

except what do we do with bounds in impl blocks?

view this post on Zulip oli (Aug 17 2021 at 11:38):

the same thing as in const fn?

view this post on Zulip oli (Aug 17 2021 at 11:39):

bounds are the same everywhere

view this post on Zulip oli (Aug 17 2021 at 11:39):

or am I missing something?

view this post on Zulip RalfJ (Aug 17 2021 at 11:39):

is this allowed?

impl<T: const Trait> Something<T> {
  const fn foo(...) {...}
  fn bar(...) {...}
}

view this post on Zulip oli (Aug 17 2021 at 11:39):

heh

view this post on Zulip oli (Aug 17 2021 at 11:39):

ok

view this post on Zulip oli (Aug 17 2021 at 11:39):

those impl blocks

view this post on Zulip oli (Aug 17 2021 at 11:40):

forgot about inherent ones

view this post on Zulip oli (Aug 17 2021 at 11:40):

yea

view this post on Zulip oli (Aug 17 2021 at 11:40):

uh

view this post on Zulip oli (Aug 17 2021 at 11:40):

it's all not great. Ignoring the const for non-const functions seems like a real mess

view this post on Zulip oli (Aug 17 2021 at 11:41):

I mean... we could just require you to re-state bounds you want const on the function

view this post on Zulip oli (Aug 17 2021 at 11:41):

"problem solved"

view this post on Zulip RalfJ (Aug 17 2021 at 11:41):

basically that block should be equivalent to having the <T: const Trait> on each fn separately, I'd say

view this post on Zulip RalfJ (Aug 17 2021 at 11:41):

if that would be rejected, then this block should be rejected

view this post on Zulip oli (Aug 17 2021 at 11:41):

yea

view this post on Zulip oli (Aug 17 2021 at 11:42):

impl<T: const Trait> Something<T> {
  const fn foo(...) {...}
  const fn bar(...) {...}
}

should not be rejected then

view this post on Zulip RalfJ (Aug 17 2021 at 11:42):

though doesnt this become even more interesting for trait impls, in particular if the trait contains both fn and const fn?

view this post on Zulip oli (Aug 17 2021 at 11:42):

traits can't do that

view this post on Zulip RalfJ (Aug 17 2021 at 11:42):

not yet

view this post on Zulip RalfJ (Aug 17 2021 at 11:42):

seems like a reasonable extension though

view this post on Zulip oli (Aug 17 2021 at 11:42):

sure :grinning: but we're in "throw away all nice syntax for future extensions" mode already

view this post on Zulip RalfJ (Aug 17 2021 at 11:43):

are we?^^ it's less about "nice" and more about being internally coherent

view this post on Zulip oli (Aug 17 2021 at 11:44):

well... you could add where bounds on the const fn

view this post on Zulip oli (Aug 17 2021 at 11:45):

oh, one thing: non-const impl blocks can't use generic params to call methods in their assoc consts if we go with const Trait not being allowed outside of const fn

view this post on Zulip RalfJ (Aug 17 2021 at 11:48):

oli said:

oh, one thing: non-const impl blocks can't use generic params to call methods in their assoc consts if we go with const Trait not being allowed outside of const fn

I dont follow, do you have an example?

view this post on Zulip oli (Aug 17 2021 at 11:49):

impl<T: Bound> SomeTrait for SomeType {
    const FOO: i32 = T::assoc_fn();
}

view this post on Zulip oli (Aug 17 2021 at 11:52):

to me, the obvious syntax here is T: const Bound

view this post on Zulip oli (Aug 17 2021 at 11:58):

I mean... we could go with allowing const Trait bounds everywhere and only allowing ?const Trait bounds (or other syntax) only on const fn and impl const Trait to mean "if used in const context"

view this post on Zulip RalfJ (Aug 17 2021 at 12:06):

ah so that is basically the same case as the "trait that mixes fn and const fn" that I brought up above

view this post on Zulip RalfJ (Aug 17 2021 at 12:06):

except the trait would mix fn and assoc consts

view this post on Zulip oli (Aug 17 2021 at 12:06):

yea

view this post on Zulip oli (Aug 17 2021 at 12:07):

but you can't add bounds on assoc consts I think?

view this post on Zulip RalfJ (Aug 17 2021 at 12:07):

yeah

view this post on Zulip oli (Aug 17 2021 at 12:07):

and on a trait impl... that makes no sense anyway

view this post on Zulip RalfJ (Aug 17 2021 at 12:07):

but this also indicates that the semantics should really be "must be const, period"

view this post on Zulip oli (Aug 17 2021 at 12:08):

I agree

view this post on Zulip oli (Aug 17 2021 at 12:08):

oli said:

I mean... we could go with allowing const Trait bounds everywhere and only allowing ?const Trait bounds (or other syntax) only on const fn and impl const Trait to mean "if used in const context"

this

view this post on Zulip RalfJ (Aug 17 2021 at 12:08):

otherwise what the heck happens in cases like this?

impl<T: const Bound> SomeTrait for SomeType {
    const FOO: i32 = T::assoc_fn();

    fn foo() -> i32 { Self::FOO }
}

view this post on Zulip oli (Aug 17 2021 at 12:08):

bugs, likely bugs will happen

view this post on Zulip RalfJ (Aug 17 2021 at 12:09):

no I mean what would even be the correct thing to do, if T: const Bound means "const when used in const context"

view this post on Zulip RalfJ (Aug 17 2021 at 12:09):

the syntax is irrelevant -- what would any kind of "const when used in const context" system do here?

view this post on Zulip RalfJ (Aug 17 2021 at 12:10):

since assoc consts have no where clauses, "const when used in const context" couldnt be used in assoc consts, I think

view this post on Zulip RalfJ (Aug 17 2021 at 12:10):

which, uh, wtf^^

view this post on Zulip RalfJ (Aug 17 2021 at 12:12):

and only allowing ?const Trait bounds (or other syntax) only on const fn and impl const Trait to mean "if used in const context"

so given the above I am not sure what allowing it on impl const Trait would lead mean exactly

view this post on Zulip oli (Aug 17 2021 at 12:41):

there is no fundamental difference between "const if in const" bounds on const fn and on impl const Trait. So

impl<T: Boo + constifinconst Trait> const OtherTrait for SomeStruct<T> {
    fn foo() { const { T::some_method() }  // illegal,
    fn bar() { <T as Trait>::some_method() } // legal
    fn boo() { <T as Boo>::some_method() } // illegal
}

view this post on Zulip oli (Aug 17 2021 at 12:44):

from the outside, so when calling <SomeStruct<T> as OtherTrait>::something(), you now need to supply a T with a const Trait impl if you are calling that function from within a const context, and can use any T: Trait otherwise

view this post on Zulip oli (Aug 17 2021 at 12:44):

this behaviour is already implemented today with the implicit syntax

view this post on Zulip RalfJ (Aug 17 2021 at 12:44):

there is no fundamental difference between "const if in const" bounds on const fn and on impl const Trait

there is, see all the discussion we just had^^

view this post on Zulip oli (Aug 17 2021 at 12:45):

no, that was about const fn vs fn in impl blocks

view this post on Zulip RalfJ (Aug 17 2021 at 12:45):

right so just add an assoc const to the above

view this post on Zulip oli (Aug 17 2021 at 12:45):

that's foo

view this post on Zulip oli (Aug 17 2021 at 12:45):

same thing

view this post on Zulip oli (Aug 17 2021 at 12:45):

can't use it

view this post on Zulip RalfJ (Aug 17 2021 at 12:46):

that doesnt seem to make much sense though

view this post on Zulip oli (Aug 17 2021 at 12:46):

it makes as much sense as not being able to do let x: T = .. for T: ?Sized

view this post on Zulip oli (Aug 17 2021 at 12:47):

you don't know the constness

view this post on Zulip oli (Aug 17 2021 at 12:47):

thus you can't rely on it

view this post on Zulip RalfJ (Aug 17 2021 at 12:47):

oli said:

it makes as much sense as not being able to do let x: T = .. for T: ?Sized

uh that comparison makes even less sense to me :P

view this post on Zulip RalfJ (Aug 17 2021 at 12:47):

oli said:

thus you can't rely on it

Im not. it's literally in a const block.^^

view this post on Zulip oli (Aug 17 2021 at 12:47):

yea, and that is an error

view this post on Zulip oli (Aug 17 2021 at 12:47):

I wrote "illegal"

view this post on Zulip RalfJ (Aug 17 2021 at 12:47):

yea and that makes no sense, is what I said ;)

view this post on Zulip RalfJ (Aug 17 2021 at 12:48):

or rather, seems to make little sense

view this post on Zulip oli (Aug 17 2021 at 12:48):

then we need an effect system afaict

view this post on Zulip oli (Aug 17 2021 at 12:48):

idk

view this post on Zulip oli (Aug 17 2021 at 12:48):

what do you feel like is the problem here?

view this post on Zulip RalfJ (Aug 17 2021 at 12:50):

what is and isnt allowed seems extremely surprising

view this post on Zulip RalfJ (Aug 17 2021 at 12:51):

impl const Trait sounds like basically all functions need to be const fn, but then the rules should be the same for foo and bar

view this post on Zulip RalfJ (Aug 17 2021 at 12:51):

but this is not impl const Trait, this is impl const? Trait

view this post on Zulip RalfJ (Aug 17 2021 at 12:52):

this is

impl<C: Constness, T: constif(C) Trait> constif(C) OtherTrait for Type

which is not at all what I expect from the impl const OtherTrait syntax

view this post on Zulip oli (Aug 17 2021 at 13:28):

no

view this post on Zulip oli (Aug 17 2021 at 13:28):

that's not what it is

view this post on Zulip oli (Aug 17 2021 at 13:29):

impl<C: Constness, T: constif(C) Trait> const OtherTrait for Type. But since T: constif(C) Trait, you cannot use it where T: const Trait is required, only where T: constif(X) Trait is required

view this post on Zulip oli (Aug 17 2021 at 13:29):

and any const item will require const Trait

view this post on Zulip RalfJ (Aug 17 2021 at 13:31):

impl<C: Constness, T: constif(C) Trait> const OtherTrait for Type

I cant make sense of that -- these C: Constness parameters only make sense when they are used more than once

view this post on Zulip oli (Aug 17 2021 at 13:31):

oh

view this post on Zulip RalfJ (Aug 17 2021 at 13:31):

they are all about tying together the constness of at least 2 things

view this post on Zulip oli (Aug 17 2021 at 13:31):

yea you're right

view this post on Zulip oli (Aug 17 2021 at 13:32):

sorry

view this post on Zulip oli (Aug 17 2021 at 13:32):

but that doesn't change the internal behaviour

view this post on Zulip RalfJ (Aug 17 2021 at 13:32):

so is my interpretation above correct, that this is impl<C: Constness, T: constif(C) Trait> constif(C) OtherTrait for Type?

view this post on Zulip oli (Aug 17 2021 at 13:32):

yes

view this post on Zulip RalfJ (Aug 17 2021 at 13:33):

right, so I was completely lead down the wrong path by the syntax then

view this post on Zulip oli (Aug 17 2021 at 13:33):

this is how the RFC specified it, too

view this post on Zulip oli (Aug 17 2021 at 13:33):

and the RFC had this written in the pseudo effect syntax similar to what you wrote

view this post on Zulip oli (Aug 17 2021 at 13:33):

otherwise we couldn't make anything generic in libstd use const

view this post on Zulip oli (Aug 17 2021 at 13:33):

as that would be a breaking change

view this post on Zulip oli (Aug 17 2021 at 13:34):

and it would create a const ecosystem in parallel to the not-const ecosystem

view this post on Zulip oli (Aug 17 2021 at 13:34):

which is exactly what we wanted to avoid

view this post on Zulip RalfJ (Aug 17 2021 at 13:34):

yeah... but after the discussion we just had about const Trait bounds, I totally did not expect const Trait imples to also be non-const impls

view this post on Zulip oli (Aug 17 2021 at 13:34):

ah

view this post on Zulip oli (Aug 17 2021 at 13:34):

well.. everything is in flux xD

view this post on Zulip RalfJ (Aug 17 2021 at 13:34):

the concept makes sense, but the syntax tripped me

view this post on Zulip oli (Aug 17 2021 at 13:34):

maybe we should do impl ?const Trait?

view this post on Zulip RalfJ (Aug 17 2021 at 13:35):

adding more ? everywhere is sure going to help avoid everyone being confused :P

view this post on Zulip oli (Aug 17 2021 at 13:35):

well

view this post on Zulip oli (Aug 17 2021 at 13:35):

come up with a better syntax XD

view this post on Zulip RalfJ (Aug 17 2021 at 13:35):

but yeah that's why I said "this is impl const? Trait" above

view this post on Zulip oli (Aug 17 2021 at 13:35):

your placement of the question mark operator does not help things :stuck_out_tongue:

view this post on Zulip RalfJ (Aug 17 2021 at 13:35):

no it makes all the difference :P

view this post on Zulip oli (Aug 17 2021 at 13:35):

oh

view this post on Zulip oli (Aug 17 2021 at 13:35):

like regex?

view this post on Zulip RalfJ (Aug 17 2021 at 13:36):

we can have a compromise: impl ?const? Trait

view this post on Zulip oli (Aug 17 2021 at 13:36):

rofl

view this post on Zulip oli (Aug 17 2021 at 13:36):

oli said:

rofl

I almost fell of my chair

view this post on Zulip RalfJ (Aug 17 2021 at 13:36):

:-)

view this post on Zulip oli (Aug 17 2021 at 13:36):

whatever. I don't care if we introduce a inferconst keyword or do some other stuff

view this post on Zulip oli (Aug 17 2021 at 13:37):

but I have come over to your side of just allowing all trait bounds in const fn and make them unusable to call and add new syntax that actually makes them callable

view this post on Zulip oli (Aug 17 2021 at 13:38):

which solves all inconsistencies between const items already being allowed to use traits and fn pointers

view this post on Zulip RalfJ (Aug 17 2021 at 13:40):

oli said:

but I have come over to your side of just allowing all trait bounds in const fn and make them unusable to call and add new syntax that actually makes them callable

"them" = the bounds, as in the const fn cannot call trait fn even though (non-const) bounds are in scope?
(alternative interpretation: them = the const fn)

view this post on Zulip oli (Aug 17 2021 at 13:44):

zes, the bounds

view this post on Zulip Lokathor (Aug 17 2021 at 14:07):

wait impl const Trait can be satisfied by a non-const trait impl some of the time? Did I skim that right?

view this post on Zulip RalfJ (Aug 17 2021 at 14:10):

impl const Trait is an impl block, what does it even mean for an impl block to be "satisifed"? bounds can be satisified, but impls...?

view this post on Zulip fee1-dead (Aug 17 2021 at 14:17):

oli said:

which is fine if we never need such a feature, but we should at least consider if we want to throw away the obvious syntax for that forever

Maybe we can introduce new syntax for that feature: const! which means "must be const". Or instead of using ?const to signify const-if-const, we use ~const or something else. I don't like the implicitness of the current syntax. It is fine to separate "always const" functions from "const if some generic parameters have const impls for some traits" functions.

view this post on Zulip Josh Triplett (Aug 17 2021 at 15:00):

! in Rust is either "not" or "macro"; we don't have any precedent for using it to mean "I mean it" or similar emphasis.

view this post on Zulip simulacrum (Aug 17 2021 at 15:01):

(or never type)

view this post on Zulip Christian Poveda (Aug 17 2021 at 15:01):

I'd rather use ?const and const to be consistent with Sized.

view this post on Zulip Lokathor (Aug 17 2021 at 15:05):

Sorry Ralf, I was thinking in arg position for a function.

view this post on Zulip Lokathor (Aug 17 2021 at 15:06):

like impl vs dyn, not like the block

view this post on Zulip oli (Aug 17 2021 at 15:44):

I like ~const, "somewhat const" :grinning:

view this post on Zulip RalfJ (Aug 17 2021 at 16:18):

Lokathor said:

Sorry Ralf, I was thinking in arg position for a function.

oh I see. I havent though about impl const Trait types, but I'd hope they are consistent with dyn const Trait :D

view this post on Zulip fee1-dead (Aug 17 2021 at 16:30):

Christian Poveda said:

I'd rather use ?const and const to be consistent with Sized.

If those are consistent with Sized, there is no way to signify that "if this type has a const impl for a trait, then this function is const, otherwise this function cannot be called in a const context" other than leaving any modifiers out.

IMO, the syntax could be: T: Foo always means a non-const bound, T: ~const Foo would mean "const-if-const" which will only be allowed for bounds on const items, and T: const Foo would mean T must implement const Foo, always (which should be in separate RFC from const_trait_impl).

view this post on Zulip RalfJ (Aug 17 2021 at 16:32):

yeah the analogy with Sized doesn't really hold up

view this post on Zulip RalfJ (Aug 17 2021 at 16:32):

the point of ?const is to tie together the constness of a bound and of the impl

view this post on Zulip RalfJ (Aug 17 2021 at 16:32):

as is made explicit by

impl<C: Constness, T: constif(C) Trait> constif(C) OtherTrait for Type

view this post on Zulip fee1-dead (Aug 17 2021 at 16:37):

RalfJ said:

to tie together the constness of a bound and of the impl

and we can just use something like ~constinstead of ?const to avoid the inconsistency with the meaning of ?Sized, problem solved

view this post on Zulip RalfJ (Aug 17 2021 at 16:39):

except for the "uh, more sigilis" effect

view this post on Zulip RalfJ (Aug 17 2021 at 16:39):

there's no easy answers in syntax, ever, and you dont "just" do anything^^

view this post on Zulip fee1-dead (Aug 17 2021 at 16:41):

It's definitely better than having a full effect system, and also better than the syntax from the current proposal IMO.

view this post on Zulip oli (Aug 17 2021 at 16:44):

we can always do something non-sigilly. T: const in const Trait :rofl:

view this post on Zulip oli (Aug 17 2021 at 16:45):

oli said:

we can always do something non-sigilly. T: const in const Trait :rofl:

for real tho: if anyone comes up with a single word, we can likely do a thing where T: your_word Trait works, because that already doesn't compile today

view this post on Zulip fee1-dead (Aug 17 2021 at 16:51):

Can we all agree that the rules of

is good and we need to find out what goes in "insert modifier here" as a next step for the RFC?

view this post on Zulip fee1-dead (Aug 17 2021 at 17:04):

Maybe trying to reach consensus here isn't a great idea... I will draft a post/pre-rfc to post on internals to discuss this more.

view this post on Zulip RalfJ (Aug 17 2021 at 17:05):

separating semantics consensus from syntax consensus is probably a good idea though :)

view this post on Zulip oli (Aug 17 2021 at 17:36):

fee1-dead said:

Can we all agree that the rules of

This is how I see it, too

view this post on Zulip RalfJ (Aug 17 2021 at 17:49):

T: (insert modifier here) Trait means const-if-const

this is well-defined in impl const Trait blocks via the desugaring above; for it to be meaningful elsewhere we should give similar desugarings

view this post on Zulip RalfJ (Aug 17 2021 at 17:50):

but if we say we only accept such bounds in impl const Trait blocks, then -- agreed :)

view this post on Zulip RalfJ (Aug 17 2021 at 17:50):

(and I mean in the top-level bounds for that block, not nested in where clauses inside the block)

view this post on Zulip fee1-dead (Aug 17 2021 at 18:18):

I would expect the const-if-const bound on a const fn to work in the same way as a const impl described above.

view this post on Zulip RalfJ (Aug 17 2021 at 18:25):

I think I can see that for inherent const fn

view this post on Zulip RalfJ (Aug 17 2021 at 18:25):

but if we ever have const fn in a trait I cant entirely make sense of this any more^^

view this post on Zulip oli (Aug 17 2021 at 18:25):

and free const fn

view this post on Zulip RalfJ (Aug 17 2021 at 18:25):

yes, I meant "non-trait"

view this post on Zulip RalfJ (Aug 17 2021 at 18:26):

which I guess for now is all of them

view this post on Zulip RalfJ (Aug 17 2021 at 18:26):

but still, this might be worth keeping in mind

view this post on Zulip oli (Aug 17 2021 at 18:26):

yea

view this post on Zulip RalfJ (Aug 17 2021 at 18:27):

RalfJ said:

I think I can see that for inherent const fn

to be concrete, it'd be something like

for<C: Constness> constif(C) fn foo<T: cosntif(C) Trait>(x: T)

view this post on Zulip RalfJ (Aug 17 2021 at 18:27):

this I remember seeing spelled out in the RFC :D

view this post on Zulip RalfJ (Aug 17 2021 at 18:27):

for the impl I dont think I saw it before, or maybe I forgot

view this post on Zulip fee1-dead (Aug 18 2021 at 16:03):

FYI: I posted a draft/pre-rfc to internals.

view this post on Zulip oli (Aug 18 2021 at 16:39):

fwiw: we got enough leeway as wg-const-eval to change the unstable feature's syntax in the ways you propose

view this post on Zulip oli (Aug 18 2021 at 16:39):

without reiterating with T-lang

view this post on Zulip fee1-dead (Aug 18 2021 at 17:01):

It will cause breakages. do we need to follow some sort of deprecation path (for ?const) before we completely change the syntax?

view this post on Zulip oli (Aug 18 2021 at 17:35):

nope, unstable feature, people need to adjust themselves

view this post on Zulip Bot+ (Aug 27 2021 at 08:42):

Tilde char '~' is very annoying to type on some variants of ISO keyboard. I would love it if Rust never used ~.

Would T = const X work instead of T: ~const X?

const fn foo<T= const X + dyn Y + Z>(input: T) -> T {
    input
}

looks much nicer in my opinion. This syntax would match with const default values and be more obvious to people who are used to param="value"; pattern.

view this post on Zulip Giacomo Stevanato (Aug 27 2021 at 09:18):

Wouldn't that imply some kind of default parameter?

view this post on Zulip Giacomo Stevanato (Aug 27 2021 at 09:19):

I agree that ~ should be avoided though

view this post on Zulip Bot+ (Aug 27 2021 at 09:21):

I would like to think of types as yet another primitive.

fn foo<T= const X + dyn Y + Z>(input: T) -> T {
    input
}

Would desugar to

fn foo<const T: Type = {const X + dyn Y + Z}>(input: T) -> T {
    input
}

view this post on Zulip oli (Aug 27 2021 at 11:23):

I don't understand why you would want to change the bound syntax. what is the difference between = and : bounds?

view this post on Zulip oli (Aug 27 2021 at 11:24):

we want to change the constness of a trait bound, not change something about the entirety of how bounds work

view this post on Zulip oli (Aug 27 2021 at 11:24):

I'd be fine with other syntaxes, but it must fit the existing system

view this post on Zulip oli (Aug 27 2021 at 11:24):

?const was nice in the previous system, because it was indeed an opt out

view this post on Zulip oli (Aug 27 2021 at 11:26):

just using plain const suggests that the generic parameter must have a const impl for that bound

view this post on Zulip oli (Aug 27 2021 at 11:26):

so we need some third option

view this post on Zulip oli (Aug 27 2021 at 11:26):

we could go with an obvious placeholder syntax like T: const if const Trait to make it clear that it's not a syntax that has had its proper bikeshed

view this post on Zulip oli (Aug 27 2021 at 11:27):

or we go with an attribute (though attributes aren't yet allowed in the middle of bounds)

view this post on Zulip oli (Aug 27 2021 at 11:28):

error: expected one of `!`, `(`, `,`, `=`, `>`, `?`, `for`, lifetime, or path, found `#`
 --> src/lib.rs:1:11
  |
1 | fn foo<T: #[allow(foo)] Eq>(){}
  |           ^ expected one of 9 possible tokens

view this post on Zulip oli (Aug 27 2021 at 11:29):

just had an idea: T: Trait<const, 'a, U, V> :upside_down:

view this post on Zulip Bot+ (Aug 27 2021 at 11:51):

Use ':' for types, '=' for traits.

Assuming

trait NewTrait: Clone + Default + MyTraitA + MyTraitB {};

const NewTrait: Vec<trait> = Clone + Default + MyTraitA + MyTraitB;

We get something like this:

// Before
fn foo<T: u8>(input: T) -> T {
    input
}
fn foo<T= const X + dyn Y + Z>(input: T) -> T {
    input
}
// After
enum Type {
    Plain(type),
    TraitCollection(Vec<trait>),
}
fn foo<const T: Type = Type::Plain(u8)>(input: T) -> T {
    input
}

fn foo<const T: Type = Type::TraitCollection(vec![const X, dyn Y, Z]>(input: T) -> T {
    input
}

Compiler would need to perform type inference on what comes after T= to check if it is value, type or trait.

fn test<T=8u32>(x: T) -> T {x} => Err("Expected Type or Trait(s). Did you mean to use 'const T:u32=8u32'?")
fn test<const T: u32=MyTrait>() -> u32{T} => Err("Expected a 'u32' value, 'MyTrait' is a trait")

view this post on Zulip Bot+ (Aug 27 2021 at 11:54):

My main issue with tilde is accessibility.

Dead Keys ('´', '`', '~', '^', '¨') are used to combine a diacritic with a letter. In my opinion they are the second hardest characters to type on Western keyboards, only behind directly typing the char code.

For example it is faster to type "a xor b" than "a ^ b"

So at least use #const, ?const, %const, !const, @const, ...

view this post on Zulip oli (Aug 27 2021 at 11:54):

uhm

view this post on Zulip oli (Aug 27 2021 at 11:55):

I'm still not sure what you are suggestinggb

view this post on Zulip oli (Aug 27 2021 at 11:55):

this is not about const generics

view this post on Zulip oli (Aug 27 2021 at 11:56):

Your proposal seems orthogonal to what we are trying to do here

view this post on Zulip oli (Aug 27 2021 at 11:56):

like a more general syntax

view this post on Zulip oli (Aug 27 2021 at 11:56):

we need a shorthand/sugar syntax, too, no matter what more general syntax we have

view this post on Zulip oli (Aug 27 2021 at 11:56):

I don't want to mix const-if-const bounds with something else that is contentious

view this post on Zulip Bot+ (Aug 27 2021 at 11:59):

My proposal's shortest variant would be fn foo<T= MyTrait>() for general case, and fn foo<T= const MyTrait>() when trait is const_trait.

view this post on Zulip oli (Aug 27 2021 at 12:41):

but how is T= MyTrait different from T: MyTrait?

view this post on Zulip oli (Aug 27 2021 at 12:41):

we want a const bound that is only const if we are in a const context

view this post on Zulip Bot+ (Aug 27 2021 at 12:52):

T= dyn MyTrait?

view this post on Zulip oli (Aug 27 2021 at 14:23):

I don't understand what that means

view this post on Zulip Giacomo Stevanato (Aug 27 2021 at 19:08):

My problem with T = MyTrait is that it's weird and counterintuitive to use it to restrict generic parameters. I would expect it to mean "if T is not specified or can't be inferred then use type MyTrait". Same for const generics, so in const T: Type = Type::TraitCollection(vec![const X, dyn Y, Z] I would expect Type::TraitCollection(vec![const X, dyn Y, Z]to be the defaul value of that const generic.

view this post on Zulip oli (Aug 27 2021 at 19:18):

I am still confused, what does any of this have to do with const bounds? It looks like there are still const bounds (const X) in your example, and I don't see how they behave as "const if in const" and not just as "must be const"

view this post on Zulip Jacob Lifshay (Aug 27 2021 at 23:42):

I suggested using const<> or const() instead of ~const: https://internals.rust-lang.org/t/pre-rfc-revamped-const-trait-impl-aka-rfc-2632/15192/16?u=programmerjake

view this post on Zulip oli (Aug 28 2021 at 15:02):

so... empty bounds mean "infer from context"?

view this post on Zulip Lokathor (Aug 28 2021 at 15:05):

"const in const" seems like the good default, and then the only other situation you'd really need is to have is "always const even if I'm not".

view this post on Zulip Lokathor (Aug 28 2021 at 15:06):

but I'm not sure if that suggests syntax

view this post on Zulip Yoshua Wuyts [he/they] (Sep 10 2021 at 09:18):

How do folks pronounce ~const when reading it? Is it: "maybe const"?

view this post on Zulip oli (Sep 10 2021 at 10:48):

"cifc"? XD

view this post on Zulip oli (Sep 10 2021 at 10:50):

I think we can just pronounce it as "const" without any modifier, as "it becomes clear from context" what kind of constness is meant

view this post on Zulip oli (Sep 10 2021 at 10:50):

it's like a pronoun, only makes sense if you said the name before

view this post on Zulip Wesley Wiser (Sep 10 2021 at 13:27):

Just put some inflection at the end: const ? ? ? :thinking:

view this post on Zulip XAMPPRocky (Sep 10 2021 at 18:29):

FWIW I would say “Tilde const”.

view this post on Zulip Gary Guo (Sep 10 2021 at 20:37):

box const

view this post on Zulip Josh Triplett (Sep 10 2021 at 21:35):

When was the ~const syntax first proposed? I remember lots of conversations about the concept of "const if thing is const", and similar mechanisms for traits for that matter. But I don't remember seeing the concrete syntax proposal.

view this post on Zulip Josh Triplett (Sep 10 2021 at 21:37):

I remember being surprised the first time I saw ~const.

view this post on Zulip Gary Guo (Sep 11 2021 at 04:44):

Josh Triplett said:

When was the ~const syntax first proposed? I remember lots of conversations about the concept of "const if thing is const", and similar mechanisms for traits for that matter. But I don't remember seeing the concrete syntax proposal.

It's proposed in this thread :grinning: If you scroll up you'll see the proposal and the pre-RFC link.

view this post on Zulip oli (Sep 11 2021 at 11:39):

It's just a placeholder (and proposed) syntax as ?const definitely sent the wrong message and we wanted to get this merged.

view this post on Zulip oli (Sep 11 2021 at 11:40):

this will need lang team sign off before anything remotely going towards stabilization happens here

view this post on Zulip oli (Sep 11 2021 at 11:40):

we would have gone with an attribute, but can't have attributes on trait bounds XD


Last updated: Oct 21 2021 at 21:02 UTC